From: Tobias C. Rittweiler Date: Sun, 31 Jan 2010 20:25:30 +0000 (+0000) Subject: 1.0.35.1: Fix CONDITION-WAIT not to signal a deadline twice (LP #512914) X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=3d83fa318b8f512dde418fa127144fca3260ec1a;p=sbcl.git 1.0.35.1: Fix CONDITION-WAIT not to signal a deadline twice (LP #512914) --- diff --git a/NEWS b/NEWS index d6ad804..aeb9409 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,8 @@ ;;;; -*- coding: utf-8; fill-column: 78 -*- +changes relative to sbcl-1.0.35: + * bug fix: SB-THREAD:CONDITION-WAIT sometimes signaled a deadline twice + in a row even though a handler defered it long into the future. + changes in sbcl-1.0.35 relative to sbcl-1.0.34: * optimization: ROUND with a single single-float or double-float argument is properly inlined when possible. diff --git a/src/code/target-thread.lisp b/src/code/target-thread.lisp index ad83197..3496854 100644 --- a/src/code/target-thread.lisp +++ b/src/code/target-thread.lisp @@ -574,7 +574,7 @@ time we reacquire MUTEX and return to the caller." (allow-with-interrupts (futex-wait (waitqueue-data-address queue) (get-lisp-obj-address me) - ;; our way if saying "no + ;; our way of saying "no ;; timeout": (or to-sec -1) (or to-usec 0)))) @@ -584,8 +584,10 @@ time we reacquire MUTEX and return to the caller." ;; them before entering the debugger, but this is ;; better than nothing. (allow-with-interrupts (get-mutex mutex))) - ;; ETIMEDOUT - ((1) (signal-deadline)) + ;; ETIMEDOUT; we know it was a timeout, yet we cannot + ;; signal a deadline unconditionally here because the + ;; call to GET-MUTEX may already have signaled it. + ((1)) ;; EINTR ((2)) ;; EWOULDBLOCK, -1 here, is the possible spurious wakeup diff --git a/tests/threads.impure.lisp b/tests/threads.impure.lisp index 3eb0fe0..7190df5 100644 --- a/tests/threads.impure.lisp +++ b/tests/threads.impure.lisp @@ -936,6 +936,37 @@ (format t "waitqueue wakeup tests done~%") +;;; Make sure that a deadline handler is not invoked twice in a row in +;;; CONDITION-WAIT. See LP #512914 for a detailed explanation. +;;; +#-sb-lutex ; See KLUDGE above: no deadlines for condition-wait+lutexes. +(with-test (:name (:condition-wait :deadlines :LP-512914)) + (let ((n 2) ; was empirically enough to trigger the bug + (mutex (sb-thread:make-mutex)) + (waitq (sb-thread:make-waitqueue)) + (threads nil) + (deadline-handler-run-twice? nil)) + (dotimes (i n) + (let ((child + (sb-thread:make-thread + #'(lambda () + (handler-bind + ((sb-sys:deadline-timeout + (let ((already? nil)) + #'(lambda (c) + (when already? + (setq deadline-handler-run-twice? t)) + (setq already? t) + (sleep 0.2) + (sb-thread:condition-broadcast waitq) + (sb-sys:defer-deadline 10.0 c))))) + (sb-sys:with-deadline (:seconds 0.1) + (sb-thread:with-mutex (mutex) + (sb-thread:condition-wait waitq mutex)))))))) + (push child threads))) + (mapc #'sb-thread:join-thread threads) + (assert (not deadline-handler-run-twice?)))) + (with-test (:name (:mutex :finalization)) (let ((a nil)) (dotimes (i 500000) diff --git a/version.lisp-expr b/version.lisp-expr index 7d64403..0f14dec 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"1.0.35" +"1.0.35.1"