1.0.5.56: conditionally re-enable interrupts interrupting current thread
[sbcl.git] / src / code / timer.lisp
index 3ad04ea..5352385 100644 (file)
@@ -338,7 +338,8 @@ triggers."
                (sb!thread:interrupt-thread thread function)
              (sb!thread:interrupt-thread-error (c)
                (declare (ignore c))
-               (warn "Timer ~S failed to interrupt thread ~S." timer thread)))))))
+               (warn "Timer ~S failed to interrupt thread ~S."
+                     timer thread)))))))
 
 ;; Called from the signal handler.
 (defun run-expired-timers ()
@@ -360,8 +361,26 @@ triggers."
 
 (defmacro sb!ext:with-timeout (expires &body body)
   #!+sb-doc
-  "Execute the body, asynchronously interrupting it and signalling a
-TIMEOUT condition after at least EXPIRES seconds have passed."
+  "Execute the body, asynchronously interrupting it and signalling a TIMEOUT
+condition after at least EXPIRES seconds have passed.
+
+Note that it is never safe to unwind from an asynchronous condition. Consider:
+
+  (defun call-with-foo (function)
+    (let (foo)
+      (unwind-protect
+         (progn
+           (setf foo (get-foo))
+           (funcall function foo))
+       (when foo
+         (release-foo foo)))))
+
+If TIMEOUT occurs after GET-FOO has executed, but before the assignment, then
+RELEASE-FOO will be missed. While individual sites like this can be made proof
+against asynchronous unwinds, this doesn't solve the fundamental issue, as all
+the frames potentially unwound through need to be proofed, which includes both
+system and application code -- and in essence proofing everything will make
+the system uninterruptible."
   (with-unique-names (timer)
     ;; FIXME: a temporary compatibility workaround for CLX, if unsafe
     ;; unwinds are handled revisit it.