[PATCH 1/3] ch: virCHMonitorNew() run new CH monitor daemonized

Kirill Shchetiniuk via Devel posted 3 patches 8 months, 4 weeks ago
[PATCH 1/3] ch: virCHMonitorNew() run new CH monitor daemonized
Posted by Kirill Shchetiniuk via Devel 8 months, 4 weeks ago
When the new CH monitor was started, it ran as a non-daemonized
process and was a child of the CH driver process. This led to a
situation where if the CH driver died, the monitor process were
killed too, terminating the running VM under the monitor. This
led to termination of all VM started under the libvirt.

Make new monitor running daemonized to avoid VMs shutdown when
driver dies. Also added a pidfile its preparetion to be able
to aquire daemon's PID.

Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
---
 src/ch/ch_domain.c  |  1 +
 src/ch/ch_domain.h  |  1 +
 src/ch/ch_monitor.c | 24 ++++++++++++++++++++++--
 src/ch/ch_process.c | 16 ++++++++++++++++
 4 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
index a08b18c5b9..c0c9acd85b 100644
--- a/src/ch/ch_domain.c
+++ b/src/ch/ch_domain.c
@@ -68,6 +68,7 @@ virCHDomainObjPrivateFree(void *data)
     virBitmapFree(priv->autoCpuset);
     virBitmapFree(priv->autoNodeset);
     virCgroupFree(priv->cgroup);
+    g_free(priv->pidfile);
     g_free(priv);
 }
 
diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
index 8dea2b2123..69a657f6af 100644
--- a/src/ch/ch_domain.h
+++ b/src/ch/ch_domain.h
@@ -36,6 +36,7 @@ struct _virCHDomainObjPrivate {
     virBitmap *autoCpuset;
     virBitmap *autoNodeset;
     virCgroup *cgroup;
+    char *pidfile;
 };
 
 #define CH_DOMAIN_PRIVATE(vm) \
diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
index 0ba927a194..1dc085a755 100644
--- a/src/ch/ch_monitor.c
+++ b/src/ch/ch_monitor.c
@@ -27,6 +27,7 @@
 
 #include "datatypes.h"
 #include "ch_conf.h"
+#include "ch_domain.h"
 #include "ch_events.h"
 #include "ch_interface.h"
 #include "ch_monitor.h"
@@ -37,6 +38,7 @@
 #include "virfile.h"
 #include "virjson.h"
 #include "virlog.h"
+#include "virpidfile.h"
 #include "virstring.h"
 
 #define VIR_FROM_THIS VIR_FROM_CH
@@ -584,6 +586,8 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
 {
     g_autoptr(virCHMonitor) mon = NULL;
     g_autoptr(virCommand) cmd = NULL;
+    virCHDomainObjPrivate *priv = vm->privateData;
+    int rv;
     int socket_fd = 0;
     int event_monitor_fd;
 
@@ -644,6 +648,7 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
     virCommandSetErrorFD(cmd, &logfile);
     virCommandNonblockingFDs(cmd);
     virCommandSetUmask(cmd, 0x002);
+
     socket_fd = chMonitorCreateSocket(mon->socketpath);
     if (socket_fd < 0) {
         virReportSystemError(errno,
@@ -655,13 +660,28 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
     virCommandAddArg(cmd, "--api-socket");
     virCommandAddArgFormat(cmd, "fd=%d", socket_fd);
     virCommandPassFD(cmd, socket_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
-
     virCommandAddArg(cmd, "--event-monitor");
     virCommandAddArgFormat(cmd, "path=%s", mon->eventmonitorpath);
+    virCommandSetPidFile(cmd, priv->pidfile);
+    virCommandDaemonize(cmd);
 
     /* launch Cloud-Hypervisor socket */
-    if (virCommandRunAsync(cmd, &mon->pid) < 0)
+    rv = virCommandRun(cmd, NULL);
+
+    if (rv == 0) {
+        if ((rv = virPidFileReadPath(priv->pidfile, &mon->pid)) < 0) {
+            virReportSystemError(-rv,
+                                 _("Domain  %1$s didn't show up"),
+                                 vm->def->name);
+            return NULL;
+        }
+        VIR_DEBUG("CH vm=%p name=%s running with pid=%lld",
+                  vm, vm->def->name, (long long)vm->pid);
+    } else {
+        VIR_DEBUG("CH vm=%p name=%s failed to spawn",
+                  vm, vm->def->name);
         return NULL;
+    }
 
     /* open the reader end of fifo before start Event Handler */
     while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
index b3eddd61e8..0954de6180 100644
--- a/src/ch/ch_process.c
+++ b/src/ch/ch_process.c
@@ -36,6 +36,7 @@
 #include "virjson.h"
 #include "virlog.h"
 #include "virnuma.h"
+#include "virpidfile.h"
 #include "virstring.h"
 #include "ch_interface.h"
 #include "ch_hostdev.h"
@@ -850,6 +851,21 @@ virCHProcessPrepareHost(virCHDriver *driver, virDomainObj *vm)
     if (virCHHostdevPrepareDomainDevices(driver, vm->def, hostdev_flags) < 0)
         return -1;
 
+    VIR_FREE(priv->pidfile);
+    if (!(priv->pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name))) {
+        virReportSystemError(errno,
+                             "%s", _("Failed to build pidfile path."));
+        return -1;
+    }
+
+    if (unlink(priv->pidfile) < 0 &&
+        errno != ENOENT) {
+        virReportSystemError(errno,
+                             _("Cannot remove stale PID file %1$s"),
+                             priv->pidfile);
+        return -1;
+    }
+
     /* Ensure no historical cgroup for this VM is lying around */
     VIR_DEBUG("Ensuring no historical cgroup is lying around");
     virDomainCgroupRemoveCgroup(vm, priv->cgroup, priv->machineName);
-- 
2.48.1
Re: [PATCH 1/3] ch: virCHMonitorNew() run new CH monitor daemonized
Posted by Ján Tomko via Devel 8 months, 2 weeks ago
On a Tuesday in 2025, Kirill Shchetiniuk via Devel wrote:
>When the new CH monitor was started, it ran as a non-daemonized
>process and was a child of the CH driver process. This led to a
>situation where if the CH driver died, the monitor process were
>killed too, terminating the running VM under the monitor. This
>led to termination of all VM started under the libvirt.
>
>Make new monitor running daemonized to avoid VMs shutdown when
>driver dies. Also added a pidfile its preparetion to be able
>to aquire daemon's PID.
>
>Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
>---
> src/ch/ch_domain.c  |  1 +
> src/ch/ch_domain.h  |  1 +
> src/ch/ch_monitor.c | 24 ++++++++++++++++++++++--
> src/ch/ch_process.c | 16 ++++++++++++++++
> 4 files changed, 40 insertions(+), 2 deletions(-)
>
>diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
>index 0ba927a194..1dc085a755 100644
>--- a/src/ch/ch_monitor.c
>+++ b/src/ch/ch_monitor.c
>@@ -644,6 +648,7 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>     virCommandSetErrorFD(cmd, &logfile);
>     virCommandNonblockingFDs(cmd);
>     virCommandSetUmask(cmd, 0x002);
>+

Nitpick: unrelated whitespace change. In some projects, these should be
squashed together with the patch changing the function as you've done here,
but in libvirt we separate them from the functional changes
(it's easier to review a patch that changes just whitespace, then the
actual functional changes are smaller)

>     socket_fd = chMonitorCreateSocket(mon->socketpath);
>     if (socket_fd < 0) {
>         virReportSystemError(errno,
>@@ -655,13 +660,28 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>     virCommandAddArg(cmd, "--api-socket");
>     virCommandAddArgFormat(cmd, "fd=%d", socket_fd);
>     virCommandPassFD(cmd, socket_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
>-

This newline could have stayed - it seprated the arguments.

>     virCommandAddArg(cmd, "--event-monitor");
>     virCommandAddArgFormat(cmd, "path=%s", mon->eventmonitorpath);
>+    virCommandSetPidFile(cmd, priv->pidfile);
>+    virCommandDaemonize(cmd);
>
>     /* launch Cloud-Hypervisor socket */
>-    if (virCommandRunAsync(cmd, &mon->pid) < 0)
>+    rv = virCommandRun(cmd, NULL);
>+
>+    if (rv == 0) {
>+        if ((rv = virPidFileReadPath(priv->pidfile, &mon->pid)) < 0) {
>+            virReportSystemError(-rv,
>+                                 _("Domain  %1$s didn't show up"),

Not a nitpick - double spaces in the error message. This is
user-visible.

Jano

>+                                 vm->def->name);
>+            return NULL;
>+        }
>+        VIR_DEBUG("CH vm=%p name=%s running with pid=%lld",
>+                  vm, vm->def->name, (long long)vm->pid);
>+    } else {
>+        VIR_DEBUG("CH vm=%p name=%s failed to spawn",
>+                  vm, vm->def->name);
>         return NULL;
>+    }
>
>     /* open the reader end of fifo before start Event Handler */
>     while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
Re: [PATCH 1/3] ch: virCHMonitorNew() run new CH monitor daemonized
Posted by Kirill Shchetiniuk via Devel 8 months, 2 weeks ago
Thanks Jan,

Didn’t noticed the issue with the white symbols when submitted a patch, next time will keep it in mind and be careful. Btw, do we have some tools to check and warn such possible issues? 

Kirill

> 2. 4. 2025 v 18:36, Ján Tomko <jtomko@redhat.com>:
> 
> On a Tuesday in 2025, Kirill Shchetiniuk via Devel wrote:
>> When the new CH monitor was started, it ran as a non-daemonized
>> process and was a child of the CH driver process. This led to a
>> situation where if the CH driver died, the monitor process were
>> killed too, terminating the running VM under the monitor. This
>> led to termination of all VM started under the libvirt.
>> 
>> Make new monitor running daemonized to avoid VMs shutdown when
>> driver dies. Also added a pidfile its preparetion to be able
>> to aquire daemon's PID.
>> 
>> Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
>> ---
>> src/ch/ch_domain.c  |  1 +
>> src/ch/ch_domain.h  |  1 +
>> src/ch/ch_monitor.c | 24 ++++++++++++++++++++++--
>> src/ch/ch_process.c | 16 ++++++++++++++++
>> 4 files changed, 40 insertions(+), 2 deletions(-)
>> 
>> diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
>> index 0ba927a194..1dc085a755 100644
>> --- a/src/ch/ch_monitor.c
>> +++ b/src/ch/ch_monitor.c
>> @@ -644,6 +648,7 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>>    virCommandSetErrorFD(cmd, &logfile);
>>    virCommandNonblockingFDs(cmd);
>>    virCommandSetUmask(cmd, 0x002);
>> +
> 
> Nitpick: unrelated whitespace change. In some projects, these should be
> squashed together with the patch changing the function as you've done here,
> but in libvirt we separate them from the functional changes
> (it's easier to review a patch that changes just whitespace, then the
> actual functional changes are smaller)
> 
>>    socket_fd = chMonitorCreateSocket(mon->socketpath);
>>    if (socket_fd < 0) {
>>        virReportSystemError(errno,
>> @@ -655,13 +660,28 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>>    virCommandAddArg(cmd, "--api-socket");
>>    virCommandAddArgFormat(cmd, "fd=%d", socket_fd);
>>    virCommandPassFD(cmd, socket_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
>> -
> 
> This newline could have stayed - it seprated the arguments.
> 
>>    virCommandAddArg(cmd, "--event-monitor");
>>    virCommandAddArgFormat(cmd, "path=%s", mon->eventmonitorpath);
>> +    virCommandSetPidFile(cmd, priv->pidfile);
>> +    virCommandDaemonize(cmd);
>> 
>>    /* launch Cloud-Hypervisor socket */
>> -    if (virCommandRunAsync(cmd, &mon->pid) < 0)
>> +    rv = virCommandRun(cmd, NULL);
>> +
>> +    if (rv == 0) {
>> +        if ((rv = virPidFileReadPath(priv->pidfile, &mon->pid)) < 0) {
>> +            virReportSystemError(-rv,
>> +                                 _("Domain  %1$s didn't show up"),
> 
> Not a nitpick - double spaces in the error message. This is
> user-visible.
> 
> Jano
> 
>> +                                 vm->def->name);
>> +            return NULL;
>> +        }
>> +        VIR_DEBUG("CH vm=%p name=%s running with pid=%lld",
>> +                  vm, vm->def->name, (long long)vm->pid);
>> +    } else {
>> +        VIR_DEBUG("CH vm=%p name=%s failed to spawn",
>> +                  vm, vm->def->name);
>>        return NULL;
>> +    }
>> 
>>    /* open the reader end of fifo before start Event Handler */
>>    while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
> <signature.asc>
Re: [PATCH 1/3] ch: virCHMonitorNew() run new CH monitor daemonized
Posted by Ján Tomko via Devel 8 months, 2 weeks ago
On a Wednesday in 2025, Kirill Shchetiniuk wrote:
>Thanks Jan,
>
>Didn’t noticed the issue with the white symbols when submitted a patch, next time will keep it in mind and be careful. Btw, do we have some tools to check and warn such possible issues?
>

For the extra/removed lines, git diff/git show.

For the translatable error message?
I'm afraid we cannot do that automatically - there are places like
--help output where we use multiple spaces to align columns in the
output.

If you left the error message untouched, I assume eventually some
translator would show up and report it / send a fix.

Jano

>Kirill
>
>> 2. 4. 2025 v 18:36, Ján Tomko <jtomko@redhat.com>:
>>
>> On a Tuesday in 2025, Kirill Shchetiniuk via Devel wrote:
>>> When the new CH monitor was started, it ran as a non-daemonized
>>> process and was a child of the CH driver process. This led to a
>>> situation where if the CH driver died, the monitor process were
>>> killed too, terminating the running VM under the monitor. This
>>> led to termination of all VM started under the libvirt.
>>>
>>> Make new monitor running daemonized to avoid VMs shutdown when
>>> driver dies. Also added a pidfile its preparetion to be able
>>> to aquire daemon's PID.
>>>
>>> Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
>>> ---
>>> src/ch/ch_domain.c  |  1 +
>>> src/ch/ch_domain.h  |  1 +
>>> src/ch/ch_monitor.c | 24 ++++++++++++++++++++++--
>>> src/ch/ch_process.c | 16 ++++++++++++++++
>>> 4 files changed, 40 insertions(+), 2 deletions(-)
>>>
>>> diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
>>> index 0ba927a194..1dc085a755 100644
>>> --- a/src/ch/ch_monitor.c
>>> +++ b/src/ch/ch_monitor.c
>>> @@ -644,6 +648,7 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>>>    virCommandSetErrorFD(cmd, &logfile);
>>>    virCommandNonblockingFDs(cmd);
>>>    virCommandSetUmask(cmd, 0x002);
>>> +
>>
>> Nitpick: unrelated whitespace change. In some projects, these should be
>> squashed together with the patch changing the function as you've done here,
>> but in libvirt we separate them from the functional changes
>> (it's easier to review a patch that changes just whitespace, then the
>> actual functional changes are smaller)
>>
>>>    socket_fd = chMonitorCreateSocket(mon->socketpath);
>>>    if (socket_fd < 0) {
>>>        virReportSystemError(errno,
>>> @@ -655,13 +660,28 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>>>    virCommandAddArg(cmd, "--api-socket");
>>>    virCommandAddArgFormat(cmd, "fd=%d", socket_fd);
>>>    virCommandPassFD(cmd, socket_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
>>> -
>>
>> This newline could have stayed - it seprated the arguments.
>>
>>>    virCommandAddArg(cmd, "--event-monitor");
>>>    virCommandAddArgFormat(cmd, "path=%s", mon->eventmonitorpath);
>>> +    virCommandSetPidFile(cmd, priv->pidfile);
>>> +    virCommandDaemonize(cmd);
>>>
>>>    /* launch Cloud-Hypervisor socket */
>>> -    if (virCommandRunAsync(cmd, &mon->pid) < 0)
>>> +    rv = virCommandRun(cmd, NULL);
>>> +
>>> +    if (rv == 0) {
>>> +        if ((rv = virPidFileReadPath(priv->pidfile, &mon->pid)) < 0) {
>>> +            virReportSystemError(-rv,
>>> +                                 _("Domain  %1$s didn't show up"),
>>
>> Not a nitpick - double spaces in the error message. This is
>> user-visible.
>>
>> Jano
>>
>>> +                                 vm->def->name);
>>> +            return NULL;
>>> +        }
>>> +        VIR_DEBUG("CH vm=%p name=%s running with pid=%lld",
>>> +                  vm, vm->def->name, (long long)vm->pid);
>>> +    } else {
>>> +        VIR_DEBUG("CH vm=%p name=%s failed to spawn",
>>> +                  vm, vm->def->name);
>>>        return NULL;
>>> +    }
>>>
>>>    /* open the reader end of fifo before start Event Handler */
>>>    while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
>> <signature.asc>
>
Re: [PATCH 1/3] ch: virCHMonitorNew() run new CH monitor daemonized
Posted by Michal Prívozník via Devel 8 months, 2 weeks ago
On 3/25/25 15:11, Kirill Shchetiniuk via Devel wrote:
> When the new CH monitor was started, it ran as a non-daemonized
> process and was a child of the CH driver process. This led to a
> situation where if the CH driver died, the monitor process were
> killed too, terminating the running VM under the monitor. This
> led to termination of all VM started under the libvirt.
> 
> Make new monitor running daemonized to avoid VMs shutdown when
> driver dies. Also added a pidfile its preparetion to be able
> to aquire daemon's PID.
> 
> Signed-off-by: Kirill Shchetiniuk <kshcheti@redhat.com>
> ---
>  src/ch/ch_domain.c  |  1 +
>  src/ch/ch_domain.h  |  1 +
>  src/ch/ch_monitor.c | 24 ++++++++++++++++++++++--
>  src/ch/ch_process.c | 16 ++++++++++++++++
>  4 files changed, 40 insertions(+), 2 deletions(-)
> 
> diff --git a/src/ch/ch_domain.c b/src/ch/ch_domain.c
> index a08b18c5b9..c0c9acd85b 100644
> --- a/src/ch/ch_domain.c
> +++ b/src/ch/ch_domain.c
> @@ -68,6 +68,7 @@ virCHDomainObjPrivateFree(void *data)
>      virBitmapFree(priv->autoCpuset);
>      virBitmapFree(priv->autoNodeset);
>      virCgroupFree(priv->cgroup);
> +    g_free(priv->pidfile);
>      g_free(priv);
>  }
>  
> diff --git a/src/ch/ch_domain.h b/src/ch/ch_domain.h
> index 8dea2b2123..69a657f6af 100644
> --- a/src/ch/ch_domain.h
> +++ b/src/ch/ch_domain.h
> @@ -36,6 +36,7 @@ struct _virCHDomainObjPrivate {
>      virBitmap *autoCpuset;
>      virBitmap *autoNodeset;
>      virCgroup *cgroup;
> +    char *pidfile;
>  };
>  
>  #define CH_DOMAIN_PRIVATE(vm) \
> diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c
> index 0ba927a194..1dc085a755 100644
> --- a/src/ch/ch_monitor.c
> +++ b/src/ch/ch_monitor.c
> @@ -27,6 +27,7 @@
>  
>  #include "datatypes.h"
>  #include "ch_conf.h"
> +#include "ch_domain.h"
>  #include "ch_events.h"
>  #include "ch_interface.h"
>  #include "ch_monitor.h"
> @@ -37,6 +38,7 @@
>  #include "virfile.h"
>  #include "virjson.h"
>  #include "virlog.h"
> +#include "virpidfile.h"
>  #include "virstring.h"
>  
>  #define VIR_FROM_THIS VIR_FROM_CH
> @@ -584,6 +586,8 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>  {
>      g_autoptr(virCHMonitor) mon = NULL;
>      g_autoptr(virCommand) cmd = NULL;
> +    virCHDomainObjPrivate *priv = vm->privateData;
> +    int rv;
>      int socket_fd = 0;
>      int event_monitor_fd;
>  
> @@ -644,6 +648,7 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>      virCommandSetErrorFD(cmd, &logfile);
>      virCommandNonblockingFDs(cmd);
>      virCommandSetUmask(cmd, 0x002);
> +
>      socket_fd = chMonitorCreateSocket(mon->socketpath);
>      if (socket_fd < 0) {
>          virReportSystemError(errno,
> @@ -655,13 +660,28 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg, int logfile)
>      virCommandAddArg(cmd, "--api-socket");
>      virCommandAddArgFormat(cmd, "fd=%d", socket_fd);
>      virCommandPassFD(cmd, socket_fd, VIR_COMMAND_PASS_FD_CLOSE_PARENT);
> -
>      virCommandAddArg(cmd, "--event-monitor");
>      virCommandAddArgFormat(cmd, "path=%s", mon->eventmonitorpath);
> +    virCommandSetPidFile(cmd, priv->pidfile);
> +    virCommandDaemonize(cmd);
>  
>      /* launch Cloud-Hypervisor socket */
> -    if (virCommandRunAsync(cmd, &mon->pid) < 0)
> +    rv = virCommandRun(cmd, NULL);
> +
> +    if (rv == 0) {
> +        if ((rv = virPidFileReadPath(priv->pidfile, &mon->pid)) < 0) {
> +            virReportSystemError(-rv,
> +                                 _("Domain  %1$s didn't show up"),
> +                                 vm->def->name);
> +            return NULL;
> +        }
> +        VIR_DEBUG("CH vm=%p name=%s running with pid=%lld",
> +                  vm, vm->def->name, (long long)vm->pid);

This needs to be mon->pid because vm->pid is set elsewhere (in the
caller virCHProcessStartRestore() after virCHProcessConnectMonitor()
returns).

> +    } else {
> +        VIR_DEBUG("CH vm=%p name=%s failed to spawn",
> +                  vm, vm->def->name);
>          return NULL;
> +    }


Alternatively, this can be simplified to:

  if (virCommandRun() < 0) {
    VIR_DEBUG(...)
    return NULL;
  }

  if ((rv = virPidFileReadPath()) < 0) {
    virReportSystemError(-rv, ...);
    return NULL;
  }

>  
>      /* open the reader end of fifo before start Event Handler */
>      while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) {
> diff --git a/src/ch/ch_process.c b/src/ch/ch_process.c
> index b3eddd61e8..0954de6180 100644
> --- a/src/ch/ch_process.c
> +++ b/src/ch/ch_process.c
> @@ -36,6 +36,7 @@
>  #include "virjson.h"
>  #include "virlog.h"
>  #include "virnuma.h"
> +#include "virpidfile.h"
>  #include "virstring.h"
>  #include "ch_interface.h"
>  #include "ch_hostdev.h"
> @@ -850,6 +851,21 @@ virCHProcessPrepareHost(virCHDriver *driver, virDomainObj *vm)
>      if (virCHHostdevPrepareDomainDevices(driver, vm->def, hostdev_flags) < 0)
>          return -1;
>  
> +    VIR_FREE(priv->pidfile);
> +    if (!(priv->pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name))) {
> +        virReportSystemError(errno,
> +                             "%s", _("Failed to build pidfile path."));
> +        return -1;
> +    }
> +
> +    if (unlink(priv->pidfile) < 0 &&
> +        errno != ENOENT) {
> +        virReportSystemError(errno,
> +                             _("Cannot remove stale PID file %1$s"),
> +                             priv->pidfile);
> +        return -1;
> +    }
> +

This works, but something similar should be in virCHProcessStop().

>      /* Ensure no historical cgroup for this VM is lying around */
>      VIR_DEBUG("Ensuring no historical cgroup is lying around");
>      virDomainCgroupRemoveCgroup(vm, priv->cgroup, priv->machineName);


Michal