forked from pool/libvirt
116 lines
4.7 KiB
Diff
116 lines
4.7 KiB
Diff
|
commit 33c6eb9689eb51dfe31dd05b24b3b6b1c948c267
|
||
|
Author: Jim Fehlig <jfehlig@suse.com>
|
||
|
Date: Thu Mar 8 15:04:48 2018 -0700
|
||
|
|
||
|
libvirtd: fix potential deadlock when reloading
|
||
|
|
||
|
It is possible to deadlock libvirtd when concurrently starting a domain
|
||
|
and restarting the daemon. Threads involved in the deadlock are
|
||
|
|
||
|
Thread 4 (Thread 0x7fc13b53e700 (LWP 64084)):
|
||
|
/lib64/libpthread.so.0
|
||
|
at util/virthread.c:154
|
||
|
at qemu/qemu_monitor.c:1083
|
||
|
cmd=0x7fc110017700, scm_fd=-1, reply=0x7fc13b53d318) at
|
||
|
qemu/qemu_monitor_json.c:305
|
||
|
cmd=0x7fc110017700,
|
||
|
reply=0x7fc13b53d318) at qemu/qemu_monitor_json.c:335
|
||
|
at qemu/qemu_monitor_json.c:1298
|
||
|
at qemu/qemu_monitor.c:1697
|
||
|
vm=0x7fc110003d00, asyncJob=QEMU_ASYNC_JOB_START) at qemu/qemu_process.c:1763
|
||
|
vm=0x7fc110003d00,
|
||
|
asyncJob=6, logCtxt=0x7fc1100089c0) at qemu/qemu_process.c:1835
|
||
|
vm=0x7fc110003d00, asyncJob=6, logCtxt=0x7fc1100089c0) at
|
||
|
qemu/qemu_process.c:2180
|
||
|
driver=0x7fc12004e1e0,
|
||
|
vm=0x7fc110003d00, asyncJob=QEMU_ASYNC_JOB_START, incoming=0x0, snapshot=0x0,
|
||
|
vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE, flags=17) at qemu/qemu_process.c:6111
|
||
|
driver=0x7fc12004e1e0,
|
||
|
vm=0x7fc110003d00, updatedCPU=0x0, asyncJob=QEMU_ASYNC_JOB_START,
|
||
|
migrateFrom=0x0,
|
||
|
migrateFd=-1, migratePath=0x0, snapshot=0x0,
|
||
|
vmop=VIR_NETDEV_VPORT_PROFILE_OP_CREATE,
|
||
|
flags=17) at qemu/qemu_process.c:6334
|
||
|
xml=0x7fc110000ed0 "<!--\nWARNING: THIS IS AN AUTO-GENERATED FILE.
|
||
|
CHANGES TO IT ARE LIKELY TO BE\nOVERWRITTEN AND LOST. Changes to this xml
|
||
|
configuration should be made using:\n virsh edit testvv\nor other
|
||
|
applicati"..., flags=0) at qemu/qemu_driver.c:1776
|
||
|
...
|
||
|
|
||
|
Thread 1 (Thread 0x7fc143c66880 (LWP 64081)):
|
||
|
/lib64/libpthread.so.0
|
||
|
at util/virthread.c:122
|
||
|
conf/nwfilter_conf.c:159
|
||
|
sig=0x7ffe0a831e30,
|
||
|
opaque=0x0) at remote/remote_daemon.c:724
|
||
|
opaque=0x558c5328b230) at rpc/virnetdaemon.c:654
|
||
|
at util/vireventpoll.c:508
|
||
|
rpc/virnetdaemon.c:858
|
||
|
remote/remote_daemon.c:1496
|
||
|
(gdb) thr 1
|
||
|
[Switching to thread 1 (Thread 0x7fc143c66880 (LWP 64081))]
|
||
|
/lib64/libpthread.so.0
|
||
|
(gdb) f 1
|
||
|
at util/virthread.c:122
|
||
|
122 pthread_rwlock_wrlock(&m->lock);
|
||
|
(gdb) p updateLock
|
||
|
$1 = {lock = {__data = {__lock = 0, __nr_readers = 1, __readers_wakeup = 0,
|
||
|
__writer_wakeup = 0, __nr_readers_queued = 0, __nr_writers_queued = 1,
|
||
|
__writer = 0,
|
||
|
__shared = 0, __rwelision = 0 '\000', __pad1 = "\000\000\000\000\000\000",
|
||
|
__pad2 = 0, __flags = 0},
|
||
|
__size = "\000\000\000\000\001", '\000' <repeats 15 times>, "\001",
|
||
|
'\000' <repeats 34 times>, __align = 4294967296}}
|
||
|
|
||
|
Reloading of the nwfilter driver is stuck waiting for a write lock, which
|
||
|
already has a reader (from qemuDomainCreateXML) in the critical section.
|
||
|
Since the reload occurs in the context of the main event loop thread,
|
||
|
libvirtd becomes deadlocked. The deadlock can be avoided by offloading
|
||
|
the reload work to a thread.
|
||
|
|
||
|
Signed-off-by: Jim Fehlig <jfehlig@suse.com>
|
||
|
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
|
||
|
|
||
|
Index: libvirt-4.1.0/src/remote/remote_daemon.c
|
||
|
===================================================================
|
||
|
--- libvirt-4.1.0.orig/src/remote/remote_daemon.c
|
||
|
+++ libvirt-4.1.0/src/remote/remote_daemon.c
|
||
|
@@ -709,20 +709,32 @@ static void daemonShutdownHandler(virNet
|
||
|
virNetDaemonQuit(dmn);
|
||
|
}
|
||
|
|
||
|
+static void daemonReloadHandlerThread(void *opague ATTRIBUTE_UNUSED)
|
||
|
+{
|
||
|
+ VIR_INFO("Reloading configuration on SIGHUP");
|
||
|
+ virHookCall(VIR_HOOK_DRIVER_DAEMON, "-",
|
||
|
+ VIR_HOOK_DAEMON_OP_RELOAD, SIGHUP, "SIGHUP", NULL, NULL);
|
||
|
+ if (virStateReload() < 0)
|
||
|
+ VIR_WARN("Error while reloading drivers");
|
||
|
+}
|
||
|
+
|
||
|
static void daemonReloadHandler(virNetDaemonPtr dmn ATTRIBUTE_UNUSED,
|
||
|
siginfo_t *sig ATTRIBUTE_UNUSED,
|
||
|
void *opaque ATTRIBUTE_UNUSED)
|
||
|
{
|
||
|
+ virThread thr;
|
||
|
+
|
||
|
if (!driversInitialized) {
|
||
|
VIR_WARN("Drivers are not initialized, reload ignored");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
- VIR_INFO("Reloading configuration on SIGHUP");
|
||
|
- virHookCall(VIR_HOOK_DRIVER_DAEMON, "-",
|
||
|
- VIR_HOOK_DAEMON_OP_RELOAD, SIGHUP, "SIGHUP", NULL, NULL);
|
||
|
- if (virStateReload() < 0)
|
||
|
- VIR_WARN("Error while reloading drivers");
|
||
|
+ if (virThreadCreate(&thr, false, daemonReloadHandlerThread, NULL) < 0) {
|
||
|
+ /*
|
||
|
+ * Not much we can do on error here except log it.
|
||
|
+ */
|
||
|
+ VIR_ERROR(_("Failed to create thread to handle daemon restart"));
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
static int daemonSetupSignals(virNetDaemonPtr dmn)
|