[libvirt] [GSoC] Design ideas for implementing cleanup attribute
Pavel Hrdina
phrdina at redhat.com
Tue May 29 12:58:57 UTC 2018
On Mon, May 28, 2018 at 09:40:41PM +0530, Sukrit Bhatnagar wrote:
> On 28 May 2018 at 13:54, Pavel Hrdina <phrdina at redhat.com> wrote:
> > On Mon, May 28, 2018 at 01:04:28PM +0530, Sukrit Bhatnagar wrote:
> >> On 25 May 2018 at 16:20, Pavel Hrdina <phrdina at redhat.com> wrote:
> >> > On Fri, May 25, 2018 at 12:06:50PM +0200, Andrea Bolognani wrote:
> >> >> On Fri, 2018-05-25 at 10:04 +0200, Pavel Hrdina wrote:
> >> >> > On Fri, May 25, 2018 at 09:13:51AM +0200, Andrea Bolognani wrote:
> >> >> > > However, I realize it might not be possible to register free
> >> >> > > functions for a native type without having to introduce something
> >> >> > > like
> >> >> > >
> >> >> > > typedef char * virString;
> >> >> > >
> >> >> > > thus causing massive churn. How does GLib deal with that?
> >> >> >
> >> >> > If you would look into GLib documentation you would see that this
> >> >> > design basically copies the one in GLib:
> >> >>
> >> >> Sorry, I should have looked up the documentation and implementation
> >> >> before asking silly questions. Guess the morning coffee hadn't quite
> >> >> kicked in yet :/
> >> >>
> >> >> > GLib libvirt
> >> >> >
> >> >> > g_autofree VIR_AUTOFREE
> >> >> > g_autoptr VIR_AUTOPTR
> >> >> > g_auto VIR_AUTOCLEAR
> >> >>
> >> >> For what it's worth, I think VIR_AUTOCLEAR is a much better name
> >> >> than g_auto :)
> >> >>
> >> >> > In GLib you are using them like this:
> >> >> >
> >> >> > g_autofree char *string = NULL;
> >> >> > g_autoptr(virDomain) dom = NULL;
> >> >> > g_auto(virDomain) dom = { 0 };
> >> >> >
> >> >> > So yes it would require to introduce a lot of typedefs for basic types
> >> >> > and that is not worth it.
> >> >>
> >> >> I'm not sure we would need so many typedefs, but there would
> >> >> certainly be a lot of churn involved.
> >> >>
> >> >> Personally, I'm not so sure it wouldn't be worth the effort,
> >> >> but it's definitely something that we can experiment with it at
> >> >> a later time instead of holding up what's already a pretty
> >> >> significant improvement.
> >> >>
> >> >> > In libvirt we would have:
> >> >> >
> >> >> > VIR_AUTOFREE char *string = NULL;
> >> >> > VIR_AUTOPTR(virDomainPtr) dom = NULL;
> >> >> > VIR_AUTOCLEAR(virDomain) dom = { 0 };
> >> >> >
> >> >> > If you notice the difference, in libvirt we can use virDomainPtr
> >> >> > directly because we have these typedefs, in GLib macro
> >> >> > G_DEFINE_AUTOPTR_CLEANUP_FUNC creates similar typedef.
> >> >>
> >> >> While I'm not a fan of our *Ptr typedefs in general, I guess this
> >> >> time I'm glad we have them because VIR_AUTOPTR() doesn't hide the
> >> >> fact that what you're declaring is a pointer; that is, the macro
> >> >> argument is also exactly the type of the variable.
> >> >
> >> > So let's make a summary of how it could look like:
> >> >
> >> > VIR_AUTOFREE(char *) string = NULL;
> >> > VIR_AUTOPTR(virDomainPtr) vm = NULL;
> >> > VIR_AUTOCLEAR(virDomain) dom = { 0 };
> >> >
> >> > VIR_DEFINE_AUTOFREE_FUNC(virDomainPtr, virDomainFree);
> >> > VIR_DEFINE_AUTOCLEAR_FUNC(virDomain, virDomainClear);
> >>
> >> Do we define new functions for freeing/clearing, because that is what
> >> VIR_DEFINE_AUTOFREE_FUNC seems to do.
> >>
> >>
> >> This is what new macros will look like:
> >>
> >> # define _VIR_TYPE_PTR(type) type##Ptr
> >>
> >> # define _VIR_ATTR_AUTOFREE_PTR(type) __attribute__((cleanup(type##Free)))
> >> # define _VIR_ATTR_AUTOCLOSE_PTR(type) __attribute__((cleanup(type##Close)))
> >> # define _VIR_ATTR_AUTOCLEAN_PTR(type) __attribute__((cleanup(type##Clean)))
> >>
> >> # define VIR_AUTOFREE_PTR(type) _VIR_ATTR_AUTOFREE_PTR(type) _VIR_TYPE_PTR(type)
> >
> > NACK to this, please look few lines above how the macros should be named
> > and which macros we would like to have implemented.
> >
> > There is no need to have the _VIR* helper macros and you need to
> > implement the VIR_DEFINE_* macros.
> >
> >> The problem is that our vir*Free functions take on vir*Ptr as the
> >> parameter and not
> >> vir*Ptr * (pointer to it).
> >
> > The problem is only with your current implementation, the original
> > design should not have this issue.
> >
> > The part of VIR_DEFINE_* macros is definition of new wrapper function
> > for the cleanup function which means that our existing free functions
> > are not used directly.
> >
> > GLib version of the define macro:
> >
> > #define G_DEFINE_AUTOPTR_CLEANUP_FUNC(TypeName, func) \
> > typedef TypeName *_GLIB_AUTOPTR_TYPENAME(TypeName); \
> > G_GNUC_BEGIN_IGNORE_DEPRECATIONS \
> > static inline void _GLIB_AUTOPTR_FUNC_NAME(TypeName) (TypeName **_ptr) \
> > { \
> > if (*_ptr) \
> > (func) (*_ptr); \
> > } \
> > G_GNUC_END_IGNORE_DEPRECATIONS
> >
> > Obviously we don't need the "typedef" line and the DEPRECATIONS macros.
>
>
> So, using the discussed design, I have added the following lines:
>
> # define VIR_AUTOPTR_FUNC_NAME(type) type##Free
> # define VIR_AUTOCLEAR_FUNC_NAME(type) type##Clear
I would suggest to make the generated function name more unique and not
that similar to our existing functions. For example:
virAutoPtr##type
virAutoClear##type
> # define VIR_DEFINE_AUTOPTR_FUNC(type, func) \
> static inline void VIR_AUTOPTR_FUNC_NAME(type) (type *_ptr) \
> { \
> if (*_ptr) \
> (func) (*_ptr); \
Theoretically the if is not required because our existing free functions
already check the given pointer whether it's null or not.
Also remove the extra space in (func) (*_ptr), that is GLib code-style.
In libvirt we don't put extra space after function name.
> } \
>
> # define VIR_DEFINE_AUTOCLEAR_FUNC(type, func) \
> static inline void VIR_AUTOCLEAR_FUNC_NAME(type) (type *_ptr) \
> { \
> if (*_ptr) \
> (func) (*_ptr); \
Here the if is not desired at all, usually the *_ptr would be directly
some structure so we need to pass the pointer itself:
(func)(_ptr);
> } \
>
> # define VIR_AUTOFREE(type) __attribute__((cleanup(virFree))) type
> # define VIR_AUTOPTR(type) \
> __attribute__((cleanup(VIR_AUTOPTR_FUNC_NAME(type)))) type
> # define VIR_AUTOCLEAR(type) \
> __attribute__((cleanup(VIR_AUTOCLEAR_FUNC_NAME(type)))) type
>
>
> We need to add something like this for each type to autofree:
> VIR_DEFINE_AUTOFREE_FUNC(virArpTablePtr, virArpTableFree)
That's correct, ideally this call should be together with the free
function in the same header file.
> Then we would use it like:
> VIR_AUTOFREEE(void *) nlData = NULL;
> VIR_AUTOPTR(virArpTablePtr) table = NULL;
>
> Does this seem fine?
>
> Also, I am still getting the errors by doing the above:
> ...
> *** Error in `/home/skrtbhtngr/libvirt/tests/.libs/lt-virbuftest':
> free(): invalid pointer: 0x00007ffdd073a208 ***
> ...
> *** Error in `/home/skrtbhtngr/libvirt/tools/.libs/lt-virsh':
> free(): invalid pointer: 0x00007fc42349dcf9 ***
> ...
This is strange and seems to be unrelated as you've already confirmed
>
> I am not changing or adding a new function (beside the one defined in macro),
> just using original virArpTableFree.
>
>
> Also, since I am defining these in viralloc.h, we would need to
> include ALL header
> files where *Ptr typedefs are made.
>
> We can do this in three ways:
> - Include all the needed header files in viralloc.h and invoke all
> VIR_DEFINE_AUTOFREE_FUNC macros in viralloc.h itself.
> - We make a separate file for VIR_DEFINE_AUTOFREE_FUNC invocations
> where all the required *Ptr headers can be included. Then directly include that
> new header file in all the relevant .c files.
> - We invoke VIR_DEFINE_AUTOFREE_FUNC in respective header files,
> for example, invoke:
>
> VIR_DEFINE_AUTOFREE_FUNC(virArpTablePtr, virArpTableFree)
>
> in virarptable.h, and also include viralloc.h in it. Then, we do not need extra
> includes in .c files.
As I've already noted, this is the only solution, the other two
solutions are really bad :).
Anyway, with all of these notes it would be nice to see some patches
posted to this list so everyone can see the resulting code.
Pavel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/libvir-list/attachments/20180529/737e34a1/attachment-0001.sig>
More information about the libvir-list
mailing list