[PATCH v2] As qemuMonitorJSONIOProcess() will unlock the qemu monitor, there is some extreme situation, eg qemu send message to monitor twice in a short time, where the local viriable 'msg' of qemuMonitorIOProcess() could be a wild point:

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

 



1. qemuMonitorSend() assign mon->msg to parameter 'msg', which is alse a
local variable of its caller qemuMonitorJSONCommandWithFd(), cause
eventloop to send message to monitor, then wait condition.
2. qemu send message to monitor for the first time immediately.
3. qemuMonitorIOProcess() is called, then wake up the qemuMonitorSend()
thread, but the qemuMonitorSend() thread stuck for a while as cpu pressure
or some other reasons,, which means the qemu monitor is still unlocked.
4. qemu send event message to monitor for the second time,
such as RTC_CHANGE event
5. qemuMonitorIOProcess() is called, the local viriable 'msg' is
assigned to mon->msg.
6. qemuMonitorIOProcess() call qemuMonitorJSONIOProcess() to deal with
the qemu event.
7. qemuMonitorJSONIOProcess() unlock the qemu monitor in the macro
'QEMU_MONITOR_CALLBACK', then qemuMonitorSend() thread get the mutex
and free the mon->msg, assign mon->msg to NULL.

so the local viriable 'msg' of qemuMonitorIOProcess() is a wild pointer
now.

AFAIK, it is not harmful to call again virCondBroadcast() while msg is a
wild pointer, but just in case,  we fix it in this patch.
---
 src/qemu/qemu_monitor.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 43f1d2f816..4a7013367d 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -454,6 +454,14 @@ qemuMonitorIOProcess(qemuMonitorPtr mon)
 #if DEBUG_IO
     VIR_DEBUG("Process done %d used %d", (int)mon->bufferOffset, len);
 #endif
+
+    /* As the monitor mutex was unlocked in qemuMonitorJSONIOProcess()
+     * while dealing with qemu event, mon->msg could be changed,
+     * thus we re-acquire the msg here */
+    msg = NULL;
+    if (mon->msg && mon->msg->txOffset == mon->msg->txLength) {
+        msg = mon->msg;
+
     if (msg && msg->finished)
         virCondBroadcast(&mon->notify);
     return len;
-- 
2.18.0.rc1

--
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