1.0.37.47: less pain for building threads on Darwin
authorNikodemus Siivola <nikodemus@random-state.net>
Wed, 7 Apr 2010 11:58:59 +0000 (11:58 +0000)
committerNikodemus Siivola <nikodemus@random-state.net>
Wed, 7 Apr 2010 11:58:59 +0000 (11:58 +0000)
 * Use RUN-PROGRAM for impure tests everywhere. Not only is it better
   to use the more-portable solution everywhere, we had a huge number
   of bogus failures on thread tests on Darwin due to interactions
   between fork() and thread stack cleanup.

   Addresses Launchpad bug #310208.

 * Make tests depending on mutex timeout punt on lutex platform, and
   make several test which are prone hang or crash into LDB punt on
   Darwin. ("Punt" here means "call ERROR" so we get a test failure.)

 * Disable mailbox tests prone to hang on Darwin.

 ...so building threads on Darwin means one actually has a prayer or
 running the tests with useful results -- and the failures are real
 Darwin problems.

contrib/sb-concurrency/tests/test-mailbox.lisp
src/code/target-thread.lisp
tests/run-program.impure.lisp
tests/run-tests.lisp
tests/threads.impure.lisp
tests/timer.impure.lisp
version.lisp-expr

index f69628a..a0f0386 100644 (file)
@@ -38,7 +38,9 @@
   (3 nil (#\1 #\2 #\3) nil)
   (0 t nil t))
 
-#+sb-thread
+;;; FIXME: Several tests disabled on Darwin due to hangs. Something not right
+;;; with mailboxes -- or possibly semaphores -- there.
+#+(and sb-thread (not darwin))
 (progn
 
 ;; Dummy struct for ATOMIC-INCF to work.
index 9ab61b1..8c7c1fe 100644 (file)
@@ -361,8 +361,7 @@ HOLDING-MUTEX-P."
   #!+sb-doc
   "Deprecated in favor of GRAB-MUTEX."
   (declare (type mutex mutex) (optimize (speed 3))
-           #!-sb-thread (ignore waitp timeout)
-           #!+sb-lutex  (ignore timeout))
+           #!-sb-thread (ignore waitp timeout))
   (unless new-owner
     (setq new-owner *current-thread*))
   (let ((old (mutex-%owner mutex)))
@@ -385,12 +384,15 @@ HOLDING-MUTEX-P."
     ;; but has that been checked?) (2) after the lutex call, but
     ;; before setting the mutex owner.
     #!+sb-lutex
-    (when (zerop (with-lutex-address (lutex (mutex-lutex mutex))
-                   (if waitp
-                       (with-interrupts (%lutex-lock lutex))
-                       (%lutex-trylock lutex))))
-      (setf (mutex-%owner mutex) new-owner)
-      t)
+    (progn
+      (when timeout
+        (error "Mutex timeouts not supported on this platform."))
+      (when (zerop (with-lutex-address (lutex (mutex-lutex mutex))
+                    (if waitp
+                        (with-interrupts (%lutex-lock lutex))
+                        (%lutex-trylock lutex))))
+       (setf (mutex-%owner mutex) new-owner)
+       t))
     #!-sb-lutex
     ;; This is a direct translation of the Mutex 2 algorithm from
     ;; "Futexes are Tricky" by Ulrich Drepper.
@@ -444,7 +446,8 @@ non-NIL and the mutex is in use, sleep until it is available.
 
 If TIMEOUT is given, it specifies a relative timeout, in seconds, on
 how long GRAB-MUTEX should try to acquire the lock in the contested
-case.
+case. Unsupported on :SB-LUTEX platforms (eg. Darwin), where a non-NIL
+TIMEOUT signals an error.
 
 If GRAB-MUTEX returns T, the lock acquisition was successful. In case
 of WAITP being NIL, or an expired TIMEOUT, GRAB-MUTEX may also return
@@ -468,9 +471,6 @@ Notes:
     ALLOW-WITH-INTERRUPTS allows the call to be interrupted from
     sleep.
 
-  - The TIMEOUT parameter is currently only supported on non-SB-LUTEX
-    platforms like Linux or BSD.
-
   - (GRAB-MUTEX <mutex> :timeout 0.0) differs from
     (GRAB-MUTEX <mutex> :waitp nil) in that the former may signal a
     DEADLINE-TIMEOUT if the global deadline was due already on
index f02cfa0..edae1fb 100644 (file)
 ;; forked process' signal mask to defaults. But the default is `stop'
 ;; of which we can be notified asynchronously by providing a status hook.
 (with-test (:name (:run-program :inherit-stdin))
+  #+(and darwin sb-thread)
+  (error "Hangs on threaded Darwin.")
   (let (stopped)
     (flet ((status-hook (proc)
              (case (sb-ext:process-status proc)
index bcd090d..67ba274 100644 (file)
     (append-failures)))
 
 (defun run-in-child-sbcl (load-forms forms)
-  (declare (ignorable load-forms))
-  #-win32
-  (let ((pid (sb-posix:fork)))
-    (cond ((= pid 0)
-           (dolist (form forms)
-             (eval form)))
-          (t
-           (let ((status (make-array 1 :element-type '(signed-byte 32))))
-             (sb-posix:waitpid pid 0 status)
-             (if (sb-posix:wifexited (aref status 0))
-                 (sb-posix:wexitstatus (aref status 0))
-                 1)))))
-  #+win32
+  ;; We used to fork() for POSIX platforms, and use this for Windows.
+  ;; However, it seems better to use the same solution everywhere.
   (process-exit-code
    (sb-ext:run-program
     (first *POSIX-ARGV*)
index a56f01f..0e43d62 100644 (file)
                                       (grab-mutex m :waitp nil)))))))))
 
 (with-test (:name (:grab-mutex :timeout :acquisition-fail))
+  #+sb-lutex
+  (error "Mutex timeout not supported here.")
   (let ((m (make-mutex)))
     (with-mutex (m)
       (assert (null (join-thread (make-thread
                                       (grab-mutex m :timeout 0.1)))))))))
 
 (with-test (:name (:grab-mutex :timeout :acquisition-success))
+  #+sb-lutex
+  (error "Mutex timeout not supported here.")
   (let ((m (make-mutex))
         (child))
     (with-mutex (m)
     (assert (eq (join-thread child) 't))))
 
 (with-test (:name (:grab-mutex :timeout+deadline))
+  #+sb-lutex
+  (error "Mutex timeout not supported here.")
   (let ((m (make-mutex)))
     (with-mutex (m)
       (assert (eq (join-thread
                   :deadline)))))
 
 (with-test (:name (:grab-mutex :waitp+deadline))
+  #+sb-lutex
+  (error "Mutex timeout not supported here.")
   (let ((m (make-mutex)))
     (with-mutex (m)
       (assert (eq (join-thread
 (defun alloc-stuff () (copy-list '(1 2 3 4 5)))
 
 (with-test (:name (:interrupt-thread :interrupt-consing-child))
+  #+darwin
+  (error "Hangs on Darwin.")
   (let ((thread (sb-thread:make-thread (lambda () (loop (alloc-stuff))))))
     (let ((killers
            (loop repeat 4 collect
 (format t "~&multi interrupt test done~%")
 
 (with-test (:name (:interrupt-thread :interrupt-consing-child :again))
+  #+darwin
+  (error "Hangs on Darwin.")
   (let ((c (make-thread (lambda () (loop (alloc-stuff))))))
     ;; NB this only works on x86: other ports don't have a symbol for
     ;; pseudo-atomic atomicity
     (assert (sb-thread:join-thread thread))))
 
 (with-test (:name (:two-threads-running-gc))
+  #+darwin
+  (error "Hangs on Darwin.")
   (let (a-done b-done)
     (make-thread (lambda ()
                    (dotimes (i 100)
 (format t "~&multiple reader hash table test done~%")
 
 (with-test (:name (:hash-table-single-accessor-parallel-gc))
+  #+darwin
+  (error "Prone to hang on Darwin due to interrupt issues.")
   (let ((hash (make-hash-table))
         (*errors* nil))
     (let ((threads (list (sb-thread:make-thread
     (assert (not deadline-handler-run-twice?))))
 
 (with-test (:name (:condition-wait :signal-deadline-with-interrupts-enabled))
+  #+darwin
+  (error "Bad Darwin")
   (let ((mutex (sb-thread:make-mutex))
         (waitq (sb-thread:make-waitqueue))
         (A-holds? :unknown)
 (format t "infodb test done~%")
 
 (with-test (:name (:backtrace))
+  #+darwin
+  (error "Prone to crash on Darwin, cause unknown.")
   ;; Printing backtraces from several threads at once used to hang the
   ;; whole SBCL process (discovered by accident due to a timer.impure
   ;; test misbehaving). The cause was that packages weren't even
 (format t "~&starting gc deadlock test: WARNING: THIS TEST WILL HANG ON FAILURE!~%")
 
 (with-test (:name (:gc-deadlock))
+  #+darwin
+  (error "Prone to hang on Darwin due to interrupt issues.")
   ;; Prior to 0.9.16.46 thread exit potentially deadlocked the
   ;; GC due to *all-threads-lock* and session lock. On earlier
   ;; versions and at least on one specific box this test is good enough
index c478eb3..df6c7ec 100644 (file)
 ;;; before they ran) and dying threads were open interrupts.
 #+sb-thread
 (with-test (:name (:timer :parallel-unschedule))
+  #+darwin
+  (error "Prone to hang on Darwin due to interrupt issues.")
   (let ((timer (sb-ext:make-timer (lambda () 42) :name "parallel schedulers"))
         (other nil))
     (flet ((flop ()
index 7b98a82..56a62a3 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.37.46"
+"1.0.37.47"