user run "firewalld-cmd --reload"
nwfilterStateReload called in main thread
step 1. virRWLockWrite(&updateLock)
step 2. virNWFilterLoadAllConfigs
step 3. virRWLockUnlock(&updateLock);
lauch a vm: qemuDomainCreateXML runs in other thread
step 1. virRWLockRead(&updateLock);
step 2. qemuProcessStart
step 3. qemuProcessWaitForMonitor
step 4. ...
step 5 virRWLockUnlock(&updateLock);
if nwfilterStateReload called in the middle of step 1 and step 5 of
qemuDomainCreateXML, it can't get the updateLock and then block the event_loop,
so event_loop can't handle the qemu-monitor messages, cause deadlock
move nwfilterStateReload into thread to fix this problem.
Signed-off-by: Wang Yechao <wang.yechao255(a)zte.com.cn>
Reviewed-by: Wang Yi <wang.yi59(a)zte.com.cn>
---
src/nwfilter/nwfilter_driver.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/nwfilter/nwfilter_driver.c b/src/nwfilter/nwfilter_driver.c
index 1ee5162..8dcc40b 100644
--- a/src/nwfilter/nwfilter_driver.c
+++ b/src/nwfilter/nwfilter_driver.c
@@ -80,18 +80,27 @@ static void nwfilterDriverUnlock(void)
}
#if HAVE_FIREWALLD
+static void nwfilterReloadThread(void *opaque ATTRIBUTE_UNUSED)
+{
+ nwfilterStateReload();
+}
static DBusHandlerResult
nwfilterFirewalldDBusFilter(DBusConnection *connection ATTRIBUTE_UNUSED,
DBusMessage *message,
void *user_data ATTRIBUTE_UNUSED)
{
+ virThread thread;
+
if (dbus_message_is_signal(message, DBUS_INTERFACE_DBUS,
"NameOwnerChanged") ||
dbus_message_is_signal(message, "org.fedoraproject.FirewallD1",
"Reloaded")) {
VIR_DEBUG("Reload in nwfilter_driver because of firewalld.");
- nwfilterStateReload();
+
+ if (virThreadCreate(&thread, false, nwfilterReloadThread, NULL) < 0) {
+ VIR_ERROR("create nwfilterThread failed.");
+ }
}
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
--
1.8.3.1