]> xenbits.xensource.com Git - libvirt.git/commitdiff
util: eventpoll: Survive EBADF on macOS
authorRoman Bolshakov <r.bolshakov@yadro.com>
Thu, 23 Aug 2018 08:49:32 +0000 (11:49 +0300)
committerMichal Privoznik <mprivozn@redhat.com>
Mon, 27 Aug 2018 08:38:26 +0000 (10:38 +0200)
Fixes:
https://www.redhat.com/archives/libvir-list/2017-January/msg00978.html

QEMU is probed through monitor fd to check capabilities during libvirtd init.
The monitor fd is closed after probing by virQEMUCapsInitQMPCommandFree
that calls virQEMUCapsInitQMPCommandAbort that calls qemuMonitorClose,
the latter one notifies the event loop via an interrupt handle in
qemuMonitorUnregister and after then closes monitor fd.

There could be a case when interrupt is sent after eventLoop is unlocked
but before virEventPollRunOnce blocks in poll, shortly before file
descriptor is closed by qemuMonitorClose. Then poll receives closed monitor
fd in fdset and returns EBADF.

EBADF is not mentioned as a valid errno on macOS poll man-page but such
behaviour can appear release-to-release, according to cpython:
https://github.com/python/cpython/blob/master/Modules/selectmodule.c#L1161

The change also fixes the issue in qemucapabilitiestest. It returns
Bad file descriptor message 25 times without the fix.

Signed-off-by: Roman Bolshakov <r.bolshakov@yadro.com>
Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
src/util/vireventpoll.c

index 13d278df1318dc7852b8d304701f3c87d1d18b3a..2fe58c7c12d302fb6811f867de7d2b857741fbe6 100644 (file)
@@ -643,6 +643,12 @@ int virEventPollRunOnce(void)
         EVENT_DEBUG("Poll got error event %d", errno);
         if (errno == EINTR || errno == EAGAIN)
             goto retry;
+#ifdef __APPLE__
+        if (errno == EBADF) {
+            virMutexLock(&eventLoop.lock);
+            goto cleanup;
+        }
+#endif
         virReportSystemError(errno, "%s",
                              _("Unable to poll on file handles"));
         return -1;
@@ -660,6 +666,9 @@ int virEventPollRunOnce(void)
     virEventPollCleanupTimeouts();
     virEventPollCleanupHandles();
 
+#ifdef __APPLE__
+ cleanup:
+#endif
     eventLoop.running = 0;
     virMutexUnlock(&eventLoop.lock);
     return 0;