0.9.15.39: futex(FUTEX_WAIT) calls need to check for EINTR
authorNikodemus Siivola <nikodemus@random-state.net>
Fri, 18 Aug 2006 16:21:54 +0000 (16:21 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Fri, 18 Aug 2006 16:21:54 +0000 (16:21 +0000)
 * Caused bogus wakeups in CONDITION-WAIT on Linux from SIGCONT.

NEWS
src/runtime/linux-os.c
tests/condition-wait-sigcont.lisp [new file with mode: 0644]
tests/threads.test.sh [new file with mode: 0644]
version.lisp-expr

diff --git a/NEWS b/NEWS
index 45cf33e..c72ccc9 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -54,6 +54,8 @@ changes in sbcl-0.9.16 relative to sbcl-0.9.15:
     types in some cases.
   * bug fix: fixed input, output and error redirection in RUN-PROGRAM
     for win32. (thanks to Mike Thomas and Yaroslav Kavenchuk)
+  * bug fix: CONDITION-WAIT could return early on Linux, if the thread was
+    interrupted and subsequently continued with SIGCONT.
 
 changes in sbcl-0.9.15 relative to sbcl-0.9.14:
   * added support for the ucs-2 external format.  (contributed by Ivan
index 8b6972c..b57b300 100644 (file)
@@ -84,7 +84,18 @@ static inline int sys_futex (void *futex, int op, int val, struct timespec *rel)
 int
 futex_wait(int *lock_word, int oldval)
 {
-    int t= sys_futex(lock_word,FUTEX_WAIT,oldval, 0);
+    int t;
+  again:
+    t = sys_futex(lock_word,FUTEX_WAIT,oldval, 0);
+
+    /* Interrupted FUTEX_WAIT calls may return early. 
+     *
+     * If someone manages to wake the futex while we're spinning
+     * around it, we will just return with -1 and errno EWOULDBLOCK,
+     * because the value has changed, so that's ok. */
+    if (t != 0 && errno == EINTR)
+       goto again;
+
     return t;
 }
 
diff --git a/tests/condition-wait-sigcont.lisp b/tests/condition-wait-sigcont.lisp
new file mode 100644 (file)
index 0000000..35adec7
--- /dev/null
@@ -0,0 +1,35 @@
+;;;; prior to sbcl 0.9.15.39 a SIGSTOP and SIGCONT while waiting
+;;;; on CONDITION-WAIT caused a spurious wakeup.
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+;;;;
+;;;; While most of SBCL is derived from the CMU CL system, the test
+;;;; files (like this one) were written from scratch after the fork
+;;;; from CMU CL.
+;;;
+;;;; This software is in the public domain and is provided with
+;;;; absoluely no warranty. See the COPYING and CREDITS files for
+;;;; more information.
+
+(use-package :sb-thread)
+
+(defvar *queue* (make-waitqueue))
+(defvar *lock* (make-mutex :name "lock"))
+
+(with-mutex (*lock*)
+  (write-line "/waiting")
+  (force-output)
+  (delete-file "condition-wait-sigcont.tmp")
+  (condition-wait *queue* *lock*)
+  (write-line "/woken")
+  (force-output)
+  (with-open-file (f "condition-wait-sigcont.tmp" :direction :output)
+    (write-line "woken!" f)))
+
+(write-line "/oops!")
+(force-output)
+
+;; sleep a bit so our runner can kill us
+(sleep 10)
+(quit)
diff --git a/tests/threads.test.sh b/tests/threads.test.sh
new file mode 100644 (file)
index 0000000..3d7a01a
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/sh
+
+# This software is part of the SBCL system. See the README file for
+# more information.
+#
+# While most of SBCL is derived from the CMU CL system, the test
+# files (like this one) were written from scratch after the fork
+# from CMU CL.
+#
+# This software is in the public domain and is provided with
+# absolutely no warranty. See the COPYING and CREDITS files for
+# more information.
+
+flag="condition-wait-sigcont.tmp"
+touch $flag
+
+../src/runtime/sbcl --core ../output/sbcl.core --load condition-wait-sigcont.lisp &
+sb_pid=$!
+
+while [ -f $flag ]; do sleep 1; done
+sleep 1
+kill -STOP $sb_pid
+kill -CONT $sb_pid
+
+sleep 2
+kill -KILL $sb_pid
+
+if [ -f $flag ]
+then
+    rm $flag
+    exit 1 # error
+else
+    exit 104 # success
+fi
index 9b78efd..8fbff01 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".)
-"0.9.15.38"
+"0.9.15.39"