[PATCH v4 5/7] nodedev: Disable/re-enable polling on the udev fd

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The event loop may get scheduled earlier than the udev event handler
thread which means that it would keep invoking the handler callback with
"new" events, while in fact it's most likely still the same event which
the handler thread hasn't managed to remove from the socket queue yet.
This is due to unwanted increments of the number of events queuing on the
socket and causes the handler thread to spam the logs with an error about
libudev returning NULL (errno == EAGAIN).

Signed-off-by: Erik Skultety <eskultet@xxxxxxxxxx>
---
 src/node_device/node_device_udev.c | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/src/node_device/node_device_udev.c b/src/node_device/node_device_udev.c
index 96760d1e4..70e15ffb8 100644
--- a/src/node_device/node_device_udev.c
+++ b/src/node_device/node_device_udev.c
@@ -1696,6 +1696,7 @@ udevEventCheckMonitorFD(struct udev_monitor *udev_monitor,
 static void
 udevEventHandleThread(void *opaque)
 {
+    udevPrivate *priv = NULL;
     udevEventThreadDataPtr privateData = opaque;
     struct udev_device *device = NULL;
     struct udev_monitor *udev_monitor = NULL;
@@ -1715,6 +1716,7 @@ udevEventHandleThread(void *opaque)
         virMutexUnlock(&privateData->lock);
 
         nodeDeviceLock();
+        priv = driver->privateData;
         udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
 
         if (!udevEventCheckMonitorFD(udev_monitor, privateData->monitor_fd)) {
@@ -1725,6 +1727,9 @@ udevEventHandleThread(void *opaque)
         device = udev_monitor_receive_device(udev_monitor);
         nodeDeviceUnlock();
 
+        /* Re-enable polling for new events on the @udev_monitor */
+        virEventUpdateHandle(priv->watch, VIR_EVENT_HANDLE_READABLE);
+
         if (!device) {
             virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                            _("udev_monitor_receive_device returned NULL"));
@@ -1750,10 +1755,12 @@ udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
                         int events ATTRIBUTE_UNUSED,
                         void *opaque)
 {
+    udevPrivate *priv = NULL;
     struct udev_monitor *udev_monitor = NULL;
     udevEventThreadDataPtr threadData = opaque;
 
     nodeDeviceLock();
+    priv = driver->privateData;
     udev_monitor = DRV_STATE_UDEV_MONITOR(driver);
 
     if (!udevEventCheckMonitorFD(udev_monitor, fd)) {
@@ -1771,6 +1778,16 @@ udevEventHandleCallback(int watch ATTRIBUTE_UNUSED,
     threadData->nevents++;
     virCondSignal(&threadData->threadCond);
     virMutexUnlock(&threadData->lock);
+
+    /* Due to scheduling, the eventloop might poll the udev monitor before the
+     * handler thread actually removes the data from the socket, thus causing it
+     * to spam errors about data not being ready yet, because
+     * udevEventHandleCallback would be invoked multiple times incrementing the
+     * counter of events queuing for a single event.
+     * Therefore we need to disable polling on the fd until the thread actually
+     * removes the data from the socket.
+     */
+    virEventUpdateHandle(priv->watch, 0);
 }
 
 
-- 
2.13.5

--
libvir-list mailing list
libvir-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/libvir-list



[Index of Archives]     [Virt Tools]     [Libvirt Users]     [Lib OS Info]     [Fedora Users]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [KDE Users]     [Fedora Tools]
  Powered by Linux