SBCL: with-timeout Is a Nice Undocumented Feature

SBCL has a nice undocumented feature, (sb-ext:with-timeout expires &body body). As far as I can tell, this is exactly analogous to the same feature in Bordeaux Threads, but that seems undocumented too.

It does not appear in the SBCL manual as of 1.3.14, but it does have a documentation string.

"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."

Here is a little demonstration on how to use it.

(handler-case
    (sb-ext:with-timeout 3
      (format t "Hello, world.~%")
      (sleep 5)
      (format t "Goodbye, world.~%"))
  (sb-ext:timeout (e)
    (format t "~a~%" e)))

This will print out

Hello, world.
Timeout occurred.

Enjoy.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: