summaryrefslogtreecommitdiff
path: root/libguile/threads.c
diff options
context:
space:
mode:
authorAndy Wingo <wingo@pobox.com>2017-01-08 13:18:13 +0100
committerAndy Wingo <wingo@pobox.com>2017-01-08 13:18:13 +0100
commit12eb7b8256f579fab60ebe0b38eb8788c1276eb8 (patch)
tree5c70aee46e8d0201e328744e1fedfb67a81940c9 /libguile/threads.c
parenta000e5c38d50883c517214776dda36f4e478ebad (diff)
downloadguile-12eb7b8256f579fab60ebe0b38eb8788c1276eb8.tar.gz
Prevent some interrupts of wait-condition-variable
* libguile/threads.c (timed_wait): Disable interrupts while reacquiring mutex after wait-condition-variable.
Diffstat (limited to 'libguile/threads.c')
-rw-r--r--libguile/threads.c28
1 files changed, 18 insertions, 10 deletions
diff --git a/libguile/threads.c b/libguile/threads.c
index 64bef8c89..7d91a01da 100644
--- a/libguile/threads.c
+++ b/libguile/threads.c
@@ -1290,7 +1290,23 @@ timed_wait (enum scm_mutex_kind kind, struct scm_mutex *m, struct scm_cond *c,
err = block_self (c->waiting, &m->lock, waittime);
/* We woke up for some reason. Reacquire the mutex before doing
- anything else. */
+ anything else.
+
+ FIXME: We disable interrupts while reacquiring the mutex. If
+ we allow interrupts here, there's the risk of a nonlocal exit
+ before we reaquire the mutex, which would be visible to user
+ code.
+
+ For example the unwind handler in
+
+ (with-mutex m (wait-condition-variable c m))
+
+ that tries to unlock M could see M in an already-unlocked
+ state, if an interrupt while waiting on C caused the wait to
+ abort and the woke thread lost the race to reacquire M. That's
+ not great. Maybe it's necessary but for now we just disable
+ interrupts while reaquiring a mutex after a wait. */
+ current_thread->block_asyncs++;
if (kind == SCM_MUTEX_RECURSIVE &&
scm_is_eq (m->owner, current_thread->handle))
{
@@ -1307,16 +1323,8 @@ timed_wait (enum scm_mutex_kind kind, struct scm_mutex *m, struct scm_cond *c,
break;
}
block_self (m->waiting, &m->lock, waittime);
- if (scm_is_eq (m->owner, SCM_BOOL_F))
- {
- m->owner = current_thread->handle;
- scm_i_pthread_mutex_unlock (&m->lock);
- break;
- }
- scm_i_pthread_mutex_unlock (&m->lock);
- scm_async_tick ();
- scm_i_scm_pthread_mutex_lock (&m->lock);
}
+ current_thread->block_asyncs--;
/* Now that we have the mutex again, handle the return value. */
if (err == 0)