From c97e05b47236081529c73981b7624e0e0bb98fad Mon Sep 17 00:00:00 2001 From: Nikodemus Siivola Date: Fri, 18 Aug 2006 16:21:54 +0000 Subject: [PATCH] 0.9.15.39: futex(FUTEX_WAIT) calls need to check for EINTR * Caused bogus wakeups in CONDITION-WAIT on Linux from SIGCONT. --- NEWS | 2 ++ src/runtime/linux-os.c | 13 ++++++++++++- tests/condition-wait-sigcont.lisp | 35 +++++++++++++++++++++++++++++++++++ tests/threads.test.sh | 34 ++++++++++++++++++++++++++++++++++ version.lisp-expr | 2 +- 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 tests/condition-wait-sigcont.lisp create mode 100644 tests/threads.test.sh diff --git a/NEWS b/NEWS index 45cf33e..c72ccc9 100644 --- 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 diff --git a/src/runtime/linux-os.c b/src/runtime/linux-os.c index 8b6972c..b57b300 100644 --- a/src/runtime/linux-os.c +++ b/src/runtime/linux-os.c @@ -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 index 0000000..35adec7 --- /dev/null +++ b/tests/condition-wait-sigcont.lisp @@ -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 index 0000000..3d7a01a --- /dev/null +++ b/tests/threads.test.sh @@ -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 diff --git a/version.lisp-expr b/version.lisp-expr index 9b78efd..8fbff01 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".) -"0.9.15.38" +"0.9.15.39" -- 1.7.10.4