From 2c3e4a0f6e23dbe9247d87d4bfd6951d5c9297c3 Mon Sep 17 00:00:00 2001 From: Marc Hartmayer Date: Tue, 23 Apr 2024 20:09:00 +0200 Subject: [PATCH] node_device_udev: nodeStateShutdownPrepare: Disconnect the signals explicitly The documentation of gobject signals reads: "If you are connecting handlers to signals and using a GObject instance as your signal handler user data, you should remember to pair calls to g_signal_connect() with calls to g_signal_handler_disconnect() or g_signal_handlers_disconnect_by_func(). While signal handlers are automatically disconnected when the object emitting the signal is finalised..." [1] This means that the signal handlers are automatically disconnected as soon as the `priv->mdevCtlMonitors` are finalised/released by `udevEventDataDispose`. But this also means that it's possible that new work is tried to be scheduled for the workerpool by the `mdevctlEventHandleCallback` (main thread context) even if the workerpool has already been stopped by `nodeStateShutdownWait`. To fully understand this, it's important to know that the main loop of the main thread is still running for some time even after `nodeStateShutdownPrepare` has been called. Let's avoid this situation by explicitly disconnect the signals during `nodeStateShutdownPrepare`, which is called in the main thread, so that no new work is attempted to be scheduled for the worker pool. [1] https://docs.gtk.org/gobject/signals.html#memory-management-of-signal-handlers Reviewed-by: Jonathon Jongsma Reviewed-by: Boris Fiuczynski Signed-off-by: Marc Hartmayer --- src/node_device/node_device_udev.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c index ee7ff0202a..a9ae3c31c4 100644 --- a/src/node_device/node_device_udev.c +++ b/src/node_device/node_device_udev.c @@ -2226,6 +2226,12 @@ nodeStateShutdownPrepare(void) if (!priv) return 0; + VIR_WITH_MUTEX_LOCK_GUARD(&priv->mdevctlLock) { + GList *tmp; + for (tmp = priv->mdevctlMonitors; tmp; tmp = tmp->next) + g_signal_handlers_disconnect_by_data(tmp->data, priv); + } + VIR_WITH_OBJECT_LOCK_GUARD(priv) { if (priv->mdevctlTimeout != -1) { virEventRemoveTimeout(priv->mdevctlTimeout);