[libvirt] [PATCH V2 1/3] libxl: fix ref counting of libxlMigrationDstArgs

Michal Privoznik mprivozn at redhat.com
Thu Aug 20 00:16:04 UTC 2015


On 07.08.2015 19:53, Jim Fehlig wrote:
> This patch fixes some flawed logic around ref counting the
> libxlMigrationDstArgs object.
> 
> First, when adding sockets to the event loop with
> virNetSocketAddIOCallback(), the generic virObjectFreeCallback()
> was registered as a free function, with libxlMigrationDstArgs as
> its parameter. A reference was also taken on
> libxlMigrationDstArgs for each successful call to
> virNetSocketAddIOCallback(). The rational behind this logic was
> that the libxlMigrationDstArgs object had to out-live the socket
> objects. But virNetSocketAddIOCallback() already takes a
> reference on socket objects, ensuring their life until removed
> from the event loop and unref'ed in virNetSocketEventFree(). We
> only need to ensure libxlMigrationDstArgs lives until
> libxlDoMigrateReceive() finishes, which can be done by simply
> unref'ing libxlMigrationDstArgs at the end of
> libxlDoMigrateReceive().
> 
> The second flaw was unref'ing the sockets in the failure path of
> libxlMigrateReceive() and at the end of libxlDoMigrateReceive().
> As mentioned above, the sockets are already unref'ed by
> virNetSocketEventFree() when removed from the event loop.
> Attempting to unref the socket a second time resulted in a
> libvirtd crash since the socket was previously unref'ed and
> disposed.
> 
> Signed-off-by: Jim Fehlig <jfehlig at suse.com>
> ---
> 
> V2: Initialize args in libxlDomainMigrationPrepare
> 
>  src/libxl/libxl_migration.c | 20 ++++++--------------
>  1 file changed, 6 insertions(+), 14 deletions(-)
> 
> diff --git a/src/libxl/libxl_migration.c b/src/libxl/libxl_migration.c
> index aa9547b..f9673c8 100644
> --- a/src/libxl/libxl_migration.c
> +++ b/src/libxl/libxl_migration.c
> @@ -112,11 +112,11 @@ libxlDoMigrateReceive(void *opaque)
>          virNetSocketUpdateIOCallback(socks[i], 0);

This is pre-existing, but since the socket callback is removed right
after, it does not make much sense to update its events to listen for.

>          virNetSocketRemoveIOCallback(socks[i]);
>          virNetSocketClose(socks[i]);
> -        virObjectUnref(socks[i]);

This will leak the socks[i] object, wouldn't it? I mean, in
libxlDomainMigrationPrepare() on line 392 virNetSocketNewListenTCP() is
called. This initialize the array with object pointers. Then
virNetSocketAddIOCallback() + virNetSocketRemoveIOCallback() pair keep
the ref counter consistent. This makes me think you should not remove
this line.

>          socks[i] = NULL;
>      }
>      args->nsocks = 0;
>      VIR_FORCE_CLOSE(recvfd);
> +    virObjectUnref(args);
>  }
>  
>  
> @@ -164,11 +164,11 @@ libxlMigrateReceive(virNetSocketPtr sock,
>          virNetSocketUpdateIOCallback(socks[i], 0);
>          virNetSocketRemoveIOCallback(socks[i]);
>          virNetSocketClose(socks[i]);
> -        virObjectUnref(socks[i]);
>          socks[i] = NULL;
>      }
>      args->nsocks = 0;
>      VIR_FORCE_CLOSE(recvfd);
> +    virObjectUnref(args);
>  }
>  
>  static int
> @@ -318,7 +318,7 @@ libxlDomainMigrationPrepare(virConnectPtr dconn,
>      virNetSocketPtr *socks = NULL;
>      size_t nsocks = 0;
>      int nsocks_listen = 0;
> -    libxlMigrationDstArgs *args;
> +    libxlMigrationDstArgs *args = NULL;
>      size_t i;
>      int ret = -1;
>  
> @@ -420,22 +420,12 @@ libxlDomainMigrationPrepare(virConnectPtr dconn,
>                                        VIR_EVENT_HANDLE_READABLE,
>                                        libxlMigrateReceive,
>                                        args,
> -                                      virObjectFreeCallback) < 0)
> +                                      NULL) < 0)
>              continue;
>  
> -        /*
> -         * Successfully added sock to event loop.  Take a ref on args to
> -         * ensure it is not freed until sock is removed from the event loop.
> -         * Ref is dropped in virObjectFreeCallback after being removed
> -         * from the event loop.
> -         */
> -        virObjectRef(args);
>          nsocks_listen++;
>      }
>  
> -    /* Done with args in this function, drop reference */
> -    virObjectUnref(args);
> -
>      if (!nsocks_listen)
>          goto error;
>  
> @@ -448,6 +438,8 @@ libxlDomainMigrationPrepare(virConnectPtr dconn,
>          virObjectUnref(socks[i]);
>      }
>      VIR_FREE(socks);
> +    virObjectUnref(args);
> +
>      /* Remove virDomainObj from domain list */
>      if (vm) {
>          virDomainObjListRemove(driver->domains, vm);
> 

Otherwise looking good.

Michal




More information about the libvir-list mailing list