summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlivier Dion <olivier.dion@polymtl.ca>2022-11-05 12:59:23 -0400
committerLudovic Courtès <ludo@gnu.org>2022-11-20 18:17:32 +0100
commita1a85581f17dade76a598b48eac7d3d308e3a0a5 (patch)
treecdefae78cde8b7e9ce41d29255f8fe8136259b5a
parente47a153317c046ea5d335940412999e7dc604c33 (diff)
downloadguile-a1a85581f17dade76a598b48eac7d3d308e3a0a5.tar.gz
Fix possible deadlock in 'lock-mutex'.
If we got interrupted while waiting on our condition variable, we unlock the kernel mutex momentarily while executing asynchronous operations before putting us back into the waiting queue. However, we have to retry acquiring the mutex before getting back into the queue, otherwise it's possible that we wait indefinitely since nobody could be the owner for a while. * libguile/threads.c (lock_mutex): Try acquring the mutex after signal interruption. Signed-off-by: Ludovic Courtès <ludo@gnu.org>
-rw-r--r--libguile/threads.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/libguile/threads.c b/libguile/threads.c
index 280d306bf..0f5cf2ed5 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -1022,14 +1022,7 @@ lock_mutex (enum scm_mutex_kind kind, struct scm_mutex *m,
if (err == 0)
{
- if (scm_is_eq (m->owner, SCM_BOOL_F))
- {
- m->owner = current_thread->handle;
- scm_i_pthread_mutex_unlock (&m->lock);
- return SCM_BOOL_T;
- }
- else
- continue;
+ goto maybe_acquire;
}
else if (err == ETIMEDOUT)
{
@@ -1041,7 +1034,7 @@ lock_mutex (enum scm_mutex_kind kind, struct scm_mutex *m,
scm_i_pthread_mutex_unlock (&m->lock);
scm_async_tick ();
scm_i_scm_pthread_mutex_lock (&m->lock);
- continue;
+ goto maybe_acquire;
}
else
{
@@ -1050,6 +1043,14 @@ lock_mutex (enum scm_mutex_kind kind, struct scm_mutex *m,
errno = err;
SCM_SYSERROR;
}
+
+ maybe_acquire:
+ if (scm_is_eq (m->owner, SCM_BOOL_F))
+ {
+ m->owner = current_thread->handle;
+ scm_i_pthread_mutex_unlock (&m->lock);
+ return SCM_BOOL_T;
+ }
}
}
#undef FUNC_NAME