[Libguestfs] [PATCH libnbd v2 2/5] lib: Implement closure lifetimes.

Richard W.M. Jones rjones at redhat.com
Wed Jul 24 20:52:54 UTC 2019


On Wed, Jul 24, 2019 at 03:30:51PM -0500, Eric Blake wrote:
> On 7/24/19 11:54 AM, Richard W.M. Jones wrote:
> > Previously closures had a crude flag which tells if they are
> > persistent or transient.  Transient closures (flag = false) last for
> > the lifetime of the currently called libnbd function.  Persistent
> > closures had an indefinite lifetime which could last for as long as
> > the handle.  In language bindings handling persistent closures was
> > wasteful as we needed to register a "close callback" to free the
> > closure when the handle is closed.  But if you had submitted thousands
> > of asynchronous commands you would end up registering thousands of
> > close callbacks.
> > 
> 
> > +++ b/lib/aio.c
> > @@ -90,6 +90,17 @@ nbd_unlocked_aio_command_completed (struct nbd_handle *h,
> >    else
> >      h->cmds_done = cmd->next;
> >  
> > +  /* Free the callbacks. */
> > +  if (cmd->type != NBD_CMD_READ && cmd->cb.fn.extent)
> > +    cmd->cb.fn.extent (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
> > +                       NULL, 0, NULL, 0, NULL);
> > +  if (cmd->type == NBD_CMD_READ && cmd->cb.fn.read)
> > +    cmd->cb.fn.read (LIBNBD_CALLBACK_FREE, cmd->cb.fn_user_data,
> > +                     NULL, 0, 0, 0, NULL);
> > +  if (cmd->cb.callback)
> > +    cmd->cb.callback (LIBNBD_CALLBACK_FREE, cmd->cb.user_data,
> > +                      0, NULL);
> > +
> >    free (cmd);
> 
> nbd_aio_command_completed is skipped when a user calls nbd_close.  While
> we've documented that nbd_close loses the exit status of any unretired
> command (different from the fact that completion callbacks run on
> transition to DEAD but the handle is still around), it is still probably
> worth tweaking nbd_close's use of free_cmd_list() to still call FREE on
> any pending callbacks on commands stranded by abrupt close to allow the
> user to still avoid memory leaks.

Yes absolutely it must do this, and it's a bug in my v2
patch that it doesn't.  I'll try to fix all this up tomorrow.

> > +++ b/lib/debug.c
> > @@ -40,9 +40,11 @@ nbd_unlocked_get_debug (struct nbd_handle *h)
> >  
> >  int
> >  nbd_unlocked_set_debug_callback (struct nbd_handle *h,
> > -                                 int (*debug_fn) (void *, const char *, const char *),
> > -                                 void *data)
> > +                                 debug_fn debug_fn, void *data)
> >  {
> > +  if (h->debug_fn)
> > +    /* ignore return value */
> > +    h->debug_fn (LIBNBD_CALLBACK_FREE, h->debug_data, NULL, NULL);
> 
> Is it worth outputting a debug message just before freeing things? Or
> put differently, should this be something like
> 
> h->debug_fn (LIBNBD_CALLBACK_VALID | LIBNBD_CALLBACK_FREE,
>              h->debug_data, context, "changing debug callback");

It's basically free so why not.

> Also, should nbd_close() output a debug message about the handle
> disappearing (and if so, obviously prior to calling callback(FREE)).

OK

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
Read my programming and virtualization blog: http://rwmj.wordpress.com
Fedora Windows cross-compiler. Compile Windows programs, test, and
build Windows installers. Over 100 libraries supported.
http://fedoraproject.org/wiki/MinGW




More information about the Libguestfs mailing list