On Thu, Sep 26, 2024 at 11:11:54AM -0500, Praveen K Paladugu wrote: > > > On 9/24/2024 8:22 AM, Purna Pavan Chandra Aekkaladevi wrote: > > On Mon, Sep 23, 2024 at 04:29:35PM -0500, Praveen K Paladugu wrote: > > > > > > > > > On 9/19/2024 8:02 AM, Purna Pavan Chandra Aekkaladevi wrote: > > > > Use a FIFO(named pipe) for --event-monitor option in CH. Introduce a new > > > > thread, `virCHEventHandlerLoop`, to continuously monitor and handle > > > > events from cloud-hypervisor. > > > > > > > > Signed-off-by: Purna Pavan Chandra Aekkaladevi <paekkaladevi@xxxxxxxxxxxxxxxxxxx> > > > > Co-authored-by: Vineeth Pillai <viremana@xxxxxxxxxxxxxxxxxxx> > > > > --- > > > > po/POTFILES | 1 + > > > > src/ch/ch_events.c | 96 +++++++++++++++++++++++++++++++++++++++++++++ > > > > src/ch/ch_events.h | 26 ++++++++++++ > > > > src/ch/ch_monitor.c | 28 +++++++++++++ > > > > src/ch/ch_monitor.h | 3 ++ > > > > src/ch/meson.build | 2 + > > > > 6 files changed, 156 insertions(+) > > > > create mode 100644 src/ch/ch_events.c > > > > create mode 100644 src/ch/ch_events.h > > > > > > > > diff --git a/po/POTFILES b/po/POTFILES > > > > index 1ed4086d2c..d53307cec4 100644 > > > > --- a/po/POTFILES > > > > +++ b/po/POTFILES > > > > @@ -21,6 +21,7 @@ src/bhyve/bhyve_process.c > > > > src/ch/ch_conf.c > > > > src/ch/ch_domain.c > > > > src/ch/ch_driver.c > > > > +src/ch/ch_events.c > > > > src/ch/ch_interface.c > > > > src/ch/ch_monitor.c > > > > src/ch/ch_process.c > > > > diff --git a/src/ch/ch_events.c b/src/ch/ch_events.c > > > > new file mode 100644 > > > > index 0000000000..851fbc9f26 > > > > --- /dev/null > > > > +++ b/src/ch/ch_events.c > > > > @@ -0,0 +1,96 @@ > > > > +/* > > > > + * Copyright Microsoft Corp. 2024 > > > > + * > > > > + * ch_events.h: Handle Cloud-Hypervisor events > > > > > > please fix the filename here. Will fix it in V2. > > > > > > > + * > > > > + * This library is free software; you can redistribute it and/or > > > > + * modify it under the terms of the GNU Lesser General Public > > > > + * License as published by the Free Software Foundation; either > > > > + * version 2.1 of the License, or (at your option) any later version. > > > > + * > > > > + * This library is distributed in the hope that it will be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > > > + * Lesser General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU Lesser General Public > > > > + * License along with this library. If not, see > > > > + * <http://www.gnu.org/licenses/>. > > > > + */ > > > > + > > > > +#include <config.h> > > > > + > > > > +#include <fcntl.h> > > > > + > > > > +#include "ch_events.h" > > > > +#include "virfile.h" > > > > +#include "virlog.h" > > > > + > > > > +VIR_LOG_INIT("ch.ch_events"); > > > > + > > > > +static void virCHEventHandlerLoop(void *data) > > > > +{ > > > > + virCHMonitor *mon = data; > > > > + virDomainObj *vm = NULL; > > > > + int event_monitor_fd; > > > > + > > > > + VIR_DEBUG("Event handler loop thread starting"); > > > > + > > > > + while ((event_monitor_fd = open(mon->eventmonitorpath, O_RDONLY)) < 0) { > > > > + if (errno == EINTR) { > > > > + g_usleep(100000); // 100 milli seconds > > > > + continue; > > > > + } > > > > + /* > > > > + * Any other error should be a BUG(kernel/libc/libvirtd) > > > > + * (ENOMEM can happen on exceeding per-user limits) > > > > + */ > > > > + VIR_ERROR(_("Failed to open the event monitor FIFO(%1$s) read end!"), > > > > + mon->eventmonitorpath); > > > > + abort(); > > > > + } > > > > + VIR_DEBUG("Opened the event monitor FIFO(%s)", mon->eventmonitorpath); > > > > + > > > > + /* > > > > + * We would need to wait until VM is initialized. > > > > + */ > > > Does this comment apply to next while loop where the events are > > > processed? > > > > > > > No, this applies to the immediate while loop where vm ref is obtained. > > > > > > + while (!(vm = virObjectRef(mon->vm))) > > > > + g_usleep(100000); // 100 milli seconds > > > > > > In this while loop you are only getting a reference to vm object. > > > > > > > Yes. At this point, we are not sure if mon->vm is initialized. The > > parent thread initializes mon->vm only after starting this event handler > > thread. Hence, wait until we have a vm ref. > > Why do you need to wait here? Is there a race condition here? > If yes, will just waiting for a reference for vm object enough? > This is actually not needed if mon->vm is initialized before started this thread. So will do that and get rid of this loop in V2. > > > > > > > + > > > > + while (g_atomic_int_get(&mon->event_handler_stop) == 0) { > > > > + VIR_DEBUG("Reading events from event monitor file..."); > > > > + /* Read and process events here */ > > > > + } > > > > + > > > > + VIR_FORCE_CLOSE(event_monitor_fd); > > > > > > > + virObjectUnref(vm); > > > > + > > > > + VIR_DEBUG("Event handler loop thread exiting"); > > > > + return; > > > > +} > > > > + > > > > +int virCHStartEventHandler(virCHMonitor *mon) > > > > +{ > > > > + g_autofree char *name = NULL; > > > > + name = g_strdup_printf("event-handler-%d", mon->pid); > > > > > > It would be better to name the thread something similar to > > > "event-handler_ch_${pid}_${vmname}". A similar format is > > > used for cgroup naming. > > > Since there is a contraint on the length of thread name, I will follow the convention of `ch-evt-${pid}` > > > > + > > > > + virObjectRef(mon); > > > > + if (virThreadCreateFull(&mon->event_handler_thread, > > > > + false, > > > > + virCHEventHandlerLoop, > > > > + name, > > > > + false, > > > > + mon) < 0) { > > > > + virObjectUnref(mon); > > > > + return -1; > > > > + } > > > > + virObjectUnref(mon); > > > > + > > > > + g_atomic_int_set(&mon->event_handler_stop, 0); > > > > + return 0; > > > > +} > > > > + > > > > +void virCHStopEventHandler(virCHMonitor *mon) > > > > +{ > > > > + g_atomic_int_set(&mon->event_handler_stop, 1); > > > > +} > > > > diff --git a/src/ch/ch_events.h b/src/ch/ch_events.h > > > > new file mode 100644 > > > > index 0000000000..4c8a48231d > > > > --- /dev/null > > > > +++ b/src/ch/ch_events.h > > > > @@ -0,0 +1,26 @@ > > > > +/* > > > > + * Copyright Microsoft Corp. 2024 > > > > + * > > > > + * ch_events.h: header file for handling Cloud-Hypervisor events > > > > + * > > > > + * This library is free software; you can redistribute it and/or > > > > + * modify it under the terms of the GNU Lesser General Public > > > > + * License as published by the Free Software Foundation; either > > > > + * version 2.1 of the License, or (at your option) any later version. > > > > + * > > > > + * This library is distributed in the hope that it will be useful, > > > > + * but WITHOUT ANY WARRANTY; without even the implied warranty of > > > > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU > > > > + * Lesser General Public License for more details. > > > > + * > > > > + * You should have received a copy of the GNU Lesser General Public > > > > + * License along with this library. If not, see > > > > + * <http://www.gnu.org/licenses/>. > > > > + */ > > > > + > > > > +#pragma once > > > > + > > > > +#include "ch_monitor.h" > > > > + > > > > +int virCHStartEventHandler(virCHMonitor *mon); > > > > +void virCHStopEventHandler(virCHMonitor *mon); > > > > diff --git a/src/ch/ch_monitor.c b/src/ch/ch_monitor.c > > > > index 8c99fe1019..5e43bf9ef8 100644 > > > > --- a/src/ch/ch_monitor.c > > > > +++ b/src/ch/ch_monitor.c > > > > @@ -26,6 +26,7 @@ > > > > #include "datatypes.h" > > > > #include "ch_conf.h" > > > > +#include "ch_events.h" > > > > #include "ch_interface.h" > > > > #include "ch_monitor.h" > > > > #include "domain_interface.h" > > > > @@ -572,6 +573,28 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg) > > > > return NULL; > > > > } > > > > + /* Event monitor file to listen for VM state changes */ > > > > + mon->eventmonitorpath = g_strdup_printf("%s/%s-event-monitor-fifo", > > > > + cfg->stateDir, vm->def->name); > > > > + if (virFileExists(mon->eventmonitorpath) && > > > > + !virFileIsNamedPipe(mon->eventmonitorpath)) { > > > > + VIR_WARN("Monitor file (%s) is not a FIFO, trying to delete!", > > > > + mon->eventmonitorpath); > > > > + if (virFileRemove(mon->eventmonitorpath, -1, -1) < 0) { > > > > + virReportError(VIR_ERR_INTERNAL_ERROR, > > > > + _("Failed to remove the file: %1$s"), > > > > + mon->eventmonitorpath); > > > > + return NULL; > > > > + } > > > > + } > > > > + > > > This does not cover the case when eventmonitorpath exists, and is a > > > named pipe, may be, not cleaned up from a previous run. > > > > > > You are better off just deleting the file and open a new one with > > > mkfifo below. > > > Will take care in V2. > > > > + if (mkfifo(mon->eventmonitorpath, S_IWUSR | S_IRUSR) < 0 && > > > > + errno != EEXIST) { > > > > + virReportSystemError(errno, "%s", > > > > + _("Cannot create monitor FIFO")); > > > > + return NULL; > > > > + } > > > > + > > > > cmd = virCommandNew(vm->def->emulator); > > > > virCommandSetUmask(cmd, 0x002); > > > > socket_fd = chMonitorCreateSocket(mon->socketpath); > > > > @@ -593,6 +616,9 @@ virCHMonitorNew(virDomainObj *vm, virCHDriverConfig *cfg) > > > > if (virCommandRunAsync(cmd, &mon->pid) < 0) > > > > return NULL; > > > > + if (virCHStartEventHandler(mon) < 0) > > > > + return NULL; > > > > + > > > > /* get a curl handle */ > > > > mon->handle = curl_easy_init(); > > > > @@ -641,6 +667,8 @@ void virCHMonitorClose(virCHMonitor *mon) > > > > g_free(mon->eventmonitorpath); > > > > } > > > > + virCHStopEventHandler(mon); > > > > + > > > Please move virCHStopEventHandler above `if (mon->eventmonitorpath) {` > > > section. Doing so, will allow the event monitor thread to cleanly > > > exit, before you invoke `virFileRemove(mon->eventmonitorpath...` > > > > Thanks for this catch. I will move it. > > And will also apply other suggestions. > > > > > > > > > virObjectUnref(mon); > > > > } > > > > diff --git a/src/ch/ch_monitor.h b/src/ch/ch_monitor.h > > > > index 2ef8706b99..878a185f29 100644 > > > > --- a/src/ch/ch_monitor.h > > > > +++ b/src/ch/ch_monitor.h > > > > @@ -97,6 +97,9 @@ struct _virCHMonitor { > > > > char *eventmonitorpath; > > > > + virThread event_handler_thread; > > > > + int event_handler_stop; > > > > + > > > > pid_t pid; > > > > virDomainObj *vm; > > > > diff --git a/src/ch/meson.build b/src/ch/meson.build > > > > index 633966aac7..684beac1f2 100644 > > > > --- a/src/ch/meson.build > > > > +++ b/src/ch/meson.build > > > > @@ -7,6 +7,8 @@ ch_driver_sources = [ > > > > 'ch_domain.h', > > > > 'ch_driver.c', > > > > 'ch_driver.h', > > > > + 'ch_events.c', > > > > + 'ch_driver.h', > > > > 'ch_interface.c', > > > > 'ch_interface.h', > > > > 'ch_monitor.c', > > > > > > > > > -- > > > Regards, > > > Praveen K Paladugu > > > > Regards, > > Purna Pavan Chandra > > > > -- > Regards, > Praveen K Paladugu Regards, Purna Pavan Chandra