diff mbox series

[RFC,2/2] qemu-thread: Fail hard for suspecious mutex unlocks

Message ID 20221011224154.644379-3-peterx@redhat.com (mailing list archive)
State New, archived
Headers show
Series qemu-thread: Strict unlock check | expand

Commit Message

Peter Xu Oct. 11, 2022, 10:41 p.m. UTC
Add a field for QemuMutex to remember the locked status, then assert
properly when CONFIG_DEBUG_MUTEX enabled on illegal unlocks.

The pthread library is by default quite loose on this by allowing the
unlock to quietly succeed.  But that could cause the follow up things very
unpredictable so if there's a bug it'll be harder to track than failing
early at the illegal unlock.

Signed-off-by: Peter Xu <peterx@redhat.com>
---
 include/qemu/thread-posix.h |  1 +
 util/qemu-thread-common.h   | 10 ++++++++++
 2 files changed, 11 insertions(+)
diff mbox series

Patch

diff --git a/include/qemu/thread-posix.h b/include/qemu/thread-posix.h
index 5f2f3d1386..e13bd5492c 100644
--- a/include/qemu/thread-posix.h
+++ b/include/qemu/thread-posix.h
@@ -9,6 +9,7 @@  struct QemuMutex {
 #ifdef CONFIG_DEBUG_MUTEX
     const char *file;
     int line;
+    bool locked;
 #endif
     bool initialized;
 };
diff --git a/util/qemu-thread-common.h b/util/qemu-thread-common.h
index 2af6b12085..ed74bdb0d1 100644
--- a/util/qemu-thread-common.h
+++ b/util/qemu-thread-common.h
@@ -21,6 +21,7 @@  static inline void qemu_mutex_post_init(QemuMutex *mutex)
 #ifdef CONFIG_DEBUG_MUTEX
     mutex->file = NULL;
     mutex->line = 0;
+    mutex->locked = false;
 #endif
     mutex->initialized = true;
 }
@@ -37,6 +38,7 @@  static inline void qemu_mutex_post_lock(QemuMutex *mutex,
 #ifdef CONFIG_DEBUG_MUTEX
     mutex->file = file;
     mutex->line = line;
+    mutex->locked = true;
 #endif
     trace_qemu_mutex_locked(mutex, file, line);
 }
@@ -47,6 +49,14 @@  static inline void qemu_mutex_pre_unlock(QemuMutex *mutex,
 #ifdef CONFIG_DEBUG_MUTEX
     mutex->file = NULL;
     mutex->line = 0;
+    /*
+     * pthread_mutex_unlock() by default silently ignore unlocking a mutex
+     * even if it's not locked.  Make it strict with QEMU when DEBUG_MUTEX
+     * is enabled, so that we can capture it at the exact wrong unlock.
+     * It'll be easier to track this than having misterious deadlock later.
+     */
+    assert(mutex->locked);
+    mutex->locked = false;
 #endif
     trace_qemu_mutex_unlock(mutex, file, line);
 }