[libvirt] libxl driver does not notice domain killed with xl destroy

Jim Fehlig jfehlig at suse.com
Sat Dec 8 00:10:12 UTC 2018


On 12/7/18 8:47 AM, Marek Marczykowski-Górecki wrote:
> Hi,
> 
> If one kills a domain with `xl destroy`, libvirt will not notice it and
> still report the domain as running. Also trying to destroy the domain
> through libvirt will fail. The only way to recover from such a situation
> is to restart libvirt daemon.

Ouch.

> While (I think) the right answer is "don't use xl destroy", libvirt
> could do better.

Nod. Restarting libvirtd is pretty drastic.

> libxl actually report such cases via LIBXL_EVENT_TYPE_DOMAIN_DEATH, but
> it is ignored by libvirt's libxl driver.

Why don't we handle that in libxlDomainEventHandler()?

> The problem is that
> LIBXL_EVENT_TYPE_DOMAIN_DEATH is also reported when it's triggered by
> libvirt (for example libxlDomainShutdownHandleDestroy, or
> libxlDomainDestroyFlags).

Ah, yes, now I remember why :-).

> For a proper solution I need a race-free way for checking if given
> LIBXL_EVENT_TYPE_DOMAIN_DEATH was caused by libvirt (and is already
> handled - including setting appropriate domain object state etc).
> 
> A bit of context:
> 
> https://github.com/libvirt/libvirt/blob/master/src/libxl/libxl_domain.c#L750-L765
>      libxlDomainDestroyInternal(libxlDriverPrivatePtr driver,
>                                 virDomainObjPtr vm)
>      {
>          libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
>          int ret = -1;
> 
> 
>          /* Unlock virDomainObj during destroy, which can take considerable
>           * time on large memory domains.
>           */
>          virObjectUnlock(vm);
>          ret = libxl_domain_destroy(cfg->ctx, vm->def->id, NULL);
>          virObjectLock(vm);
> 
> 
>          virObjectUnref(cfg);
>          return ret;
>      }
> 
> Example usage:
> https://github.com/libvirt/libvirt/blob/master/src/libxl/libxl_driver.c#L1357-L1409
>      static int
>      libxlDomainDestroyFlags(virDomainPtr dom,
>                              unsigned int flags)
>      {
> (...)
>          if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
>              goto cleanup;
> 
> 
>          if (virDomainObjCheckActive(vm) < 0)
>              goto endjob;
> 
> 
>          if (libxlDomainDestroyInternal(driver, vm) < 0) {
>              virReportError(VIR_ERR_INTERNAL_ERROR,
>                             _("Failed to destroy domain '%d'"), vm->def->id);
>              goto endjob;
>          }
> 
> 
>          virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
>                               VIR_DOMAIN_SHUTOFF_DESTROYED);
> 
> 
>          event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
>                                           VIR_DOMAIN_EVENT_STOPPED_DESTROYED);
> (...)
>      }
> 
> It's tricky, because domain object lock is released for the
> libxl_domain_destroy() call time and I think there is no guarantee that
> the lock will be taken back by libxlDomainDestroyInternal() before
> LIBXL_EVENT_TYPE_DOMAIN_DEATH is reported (and possibly handled). Which means
> I can't use domain object state for checking if libvirt already know
> about this domain death, because it is set to VIR_DOMAIN_SHUTOFF, after
> libxlDomainDestroyInternal() call. And while setting domain
> object state twice (once from LIBXL_EVENT_TYPE_DOMAIN_DEATH handler,
> then from libxlDomainDestroyInternal() caller) wouldn't be that bad
> (only ugly), but emitting domain lifecycle event twice would be a major
> problem.

Yes, that is a problem.

> Any ideas? Some internal flag set by libxlDomainDestroyInternal() just
> before libxl_domain_destroy() call? Where would be a place for such
> thing?

In the libxlDomainObjPrivate object, defined in libxl_domain.h?

Regards,
Jim




More information about the libvir-list mailing list