This is an automated email from the git hooks/post-receive script.

civodul pushed a commit to branch main
in repository guile.

The following commit(s) were added to refs/heads/main by this push:
     new 455ee49f5 Fix asymetric mutex locking when joining thread.
455ee49f5 is described below

commit 455ee49f5573baa1bc5237a8d49083ce588a13ee
Author: Olivier Dion <olivier.d...@polymtl.ca>
AuthorDate: Thu Jan 25 16:45:47 2024 -0500

    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 <l...@gnu.org>
---
 NEWS                          |  2 ++
 module/ice-9/threads.scm      |  4 +++-
 test-suite/tests/threads.test | 16 +++++++++++++++-
 3 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 57fc6f776..0bfbd1dd8 100644
--- a/NEWS
+++ b/NEWS
@@ -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

Reply via email to