1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-05-20 11:40:18 +02:00

Remove possible deadlock in scm_join_thread_timed

* libguile/threads.c (scm_join_thread_timed): Recheck t->exited before
  looping round to call block_self again, in case thread t has now
  exited.

* test-suite/tests/threads.test ("don't hang when joined thread
  terminates in SCM_TICK"): New test.
This commit is contained in:
Neil Jerram 2009-05-20 21:55:35 +01:00
parent 4201062de5
commit 21346c4f5e
2 changed files with 35 additions and 1 deletions

View file

@ -1161,6 +1161,16 @@ SCM_DEFINE (scm_join_thread_timed, "join-thread", 1, 2, 0,
scm_i_pthread_mutex_unlock (&t->admin_mutex);
SCM_TICK;
scm_i_scm_pthread_mutex_lock (&t->admin_mutex);
/* Check for exit again, since we just released and
reacquired the admin mutex, before the next block_self
call (which would block forever if t has already
exited). */
if (t->exited)
{
res = t->result;
break;
}
}
}

View file

@ -265,7 +265,31 @@
(pass-if "asyncs are still working 1"
(asyncs-still-working?))
)
;; scm_join_thread_timed has a SCM_TICK in the middle of it,
;; to allow asyncs to run (including signal delivery). We
;; used to have a bug whereby if the joined thread terminated
;; at the same time as the joining thread is in this SCM_TICK,
;; scm_join_thread_timed would not notice and would hang
;; forever. So in this test we are setting up the following
;; sequence of events.
;; T=0 other thread is created and starts running
;; T=2 main thread sets up an async that will sleep for 10 seconds
;; T=2 main thread calls join-thread, which will...
;; T=2 ...call the async, which starts sleeping
;; T=5 other thread finishes its work and terminates
;; T=7 async completes, main thread continues inside join-thread.
(pass-if "don't hang when joined thread terminates in SCM_TICK"
(let ((other-thread (make-thread sleep 5)))
(letrec ((delay-count 10)
(aproc (lambda ()
(set! delay-count (- delay-count 1))
(if (zero? delay-count)
(sleep 5)
(system-async-mark aproc)))))
(sleep 2)
(system-async-mark aproc)
(join-thread other-thread)))
#t))
;;
;; thread cancellation