From ecf1359191b2f796a7d63288652dd1a93525417d Mon Sep 17 00:00:00 2001 From: Ryan Lortie Date: Sun, 29 Jun 2014 17:47:10 -0400 Subject: [PATCH] GMutex (linux): detect and report some errors Detect the following two errors: - attempting to unlock a mutex that is not locked - attempting to clear a mutex that was not initialised or was initialised but is still locked Both of these are fatal errors. We avoid using g_error() here because doing so would involve calls back into the GMutex code, and if things are going off the rails then we want to avoid that. https://bugzilla.gnome.org/show_bug.cgi?id=731986 --- glib/gthread-posix.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/glib/gthread-posix.c b/glib/gthread-posix.c index f7d5d8a4e..54ef769ad 100644 --- a/glib/gthread-posix.c +++ b/glib/gthread-posix.c @@ -1289,6 +1289,11 @@ g_mutex_init (GMutex *mutex) void g_mutex_clear (GMutex *mutex) { + if G_UNLIKELY (mutex->i[0] != 0) + { + fprintf (stderr, "g_mutex_clear() called on uninitialised or locked mutex\n"); + abort (); + } } static void __attribute__((noinline)) @@ -1304,11 +1309,18 @@ g_mutex_lock_slowpath (GMutex *mutex) } static void __attribute__((noinline)) -g_mutex_unlock_slowpath (GMutex *mutex) +g_mutex_unlock_slowpath (GMutex *mutex, + guint prev) { /* We seem to get better code for the uncontended case by splitting - * out this call... + * this out... */ + if G_UNLIKELY (prev == 0) + { + fprintf (stderr, "Attempt to unlock mutex that was not locked\n"); + abort (); + } + syscall (__NR_futex, &mutex->i[0], (gsize) FUTEX_WAKE, (gsize) 1, NULL); } @@ -1323,9 +1335,13 @@ g_mutex_lock (GMutex *mutex) void g_mutex_unlock (GMutex *mutex) { + guint prev; + + prev = exchange_release (&mutex->i[0], 0); + /* 1-> 0 and we're done. Anything else and we need to signal... */ - if G_UNLIKELY (exchange_release (&mutex->i[0], 0) != 1) - g_mutex_unlock_slowpath (mutex); + if G_UNLIKELY (prev != 1) + g_mutex_unlock_slowpath (mutex, prev); } gboolean