diff options
author | Olivier Dion <olivier.dion@polymtl.ca> | 2024-01-25 16:45:47 -0500 |
---|---|---|
committer | Ludovic Courtès <ludo@gnu.org> | 2024-01-25 23:12:53 +0100 |
commit | 455ee49f5573baa1bc5237a8d49083ce588a13ee (patch) | |
tree | fbd6227383fb04c1da5234e6b0f3a150e4b24011 | |
parent | e791fbcefe873f579111b780842aae5a9bc9208d (diff) | |
download | guile-455ee49f5573baa1bc5237a8d49083ce588a13ee.tar.gz |
Fix asymetric mutex locking when joining thread.
If `join-thread' timeout, the thread mutex is not unlocked, resulting in
deadlock to the next call to it or deadlock of the thread itself when it
terminates.
Thus, always unlock the mutex.
Fixes <https://bugs.gnu.org/55356>.
* module/ice-9/threads.scm (join-thread): Always unlock thread mutex.
* test-suite/tests/threads.test (join-thread): New test to ensure the
mutex is released.
* NEWS: Update.
Signed-off-by: Ludovic Courtès <ludo@gnu.org>
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | module/ice-9/threads.scm | 4 | ||||
-rw-r--r-- | test-suite/tests/threads.test | 16 |
3 files changed, 20 insertions, 2 deletions
@@ -37,6 +37,8 @@ the compiler reports it as "possibly unused". (<https://bugs.gnu.org/64666>) ** Avoid module resolution in 'call-with-new-thread', which could deadlock (<https://bugs.gnu.org/62691>) +** Fix deadlock in 'join-thread' when timeout is hit + (<https://bugs.gnu.org/55356>) ** 'read-u8' in (scheme base) now defaults to (current-input-port) (<https://bugs.gnu.org/62690>) ** Hashing of UTF-8 symbols with non-ASCII characters avoids corruption diff --git a/module/ice-9/threads.scm b/module/ice-9/threads.scm index 048d8b085..a1e43b9fa 100644 --- a/module/ice-9/threads.scm +++ b/module/ice-9/threads.scm @@ -204,7 +204,9 @@ terminates, unless the target @var{thread} has already terminated." (wait-condition-variable cv mutex timeout) (wait-condition-variable cv mutex)) (lp)) - (else timeoutval)))))) + (else + (unlock-mutex mutex) + timeoutval)))))) (define* (try-mutex mutex) "Try to lock @var{mutex}. If the mutex is already locked, return diff --git a/test-suite/tests/threads.test b/test-suite/tests/threads.test index efdf36db2..fa89deeb2 100644 --- a/test-suite/tests/threads.test +++ b/test-suite/tests/threads.test @@ -332,7 +332,21 @@ (sleep 2) (system-async-mark aproc) (join-thread other-thread))) - #t)) + #t) + + (pass-if "do not throw exception if trying to join after timeout" + (let ((other-thread (begin-thread (pause)))) + (dynamic-wind + (const #f) + (lambda () + (join-thread other-thread 1) + ;; Up to 3.0.9, this second call would throw: "mutex + ;; already locked by thread". + ;; See <https://bugs.gnu.org/55356>. + (join-thread other-thread 1) + #t) + (lambda () + (cancel-thread other-thread)))))) ;; ;; thread cancellation |