1.0.35.1: Fix CONDITION-WAIT not to signal a deadline twice (LP #512914)
authorTobias C. Rittweiler <trittweiler@users.sourceforge.net>
Sun, 31 Jan 2010 20:25:30 +0000 (20:25 +0000)
committerTobias C. Rittweiler <trittweiler@users.sourceforge.net>
Sun, 31 Jan 2010 20:25:30 +0000 (20:25 +0000)
NEWS
src/code/target-thread.lisp
tests/threads.impure.lisp
version.lisp-expr

diff --git a/NEWS b/NEWS
index d6ad804..aeb9409 100644 (file)
--- 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.
index ad83197..3496854 100644 (file)
@@ -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
index 3eb0fe0..7190df5 100644 (file)
 
 (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)
index 7d64403..0f14dec 100644 (file)
@@ -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"