Function: with-timeout
with-timeout is a macro defined in timer.el.gz.
Signature
(with-timeout (SECONDS TIMEOUT-FORMS...) BODY)
Documentation
Run BODY, but if it doesn't finish in SECONDS seconds, give up.
If we give up, we run the TIMEOUT-FORMS and return the value of the last one. The timeout is checked whenever Emacs waits for some kind of external event (such as keyboard input, input from subprocesses, or a certain time); if the program loops without waiting in any way, the timeout will not be detected.
Probably introduced at or before Emacs version 19.31.
Source Code
;; Defined in /usr/src/emacs/lisp/emacs-lisp/timer.el.gz
(defmacro with-timeout (list &rest body)
"Run BODY, but if it doesn't finish in SECONDS seconds, give up.
If we give up, we run the TIMEOUT-FORMS and return the value of the last one.
The timeout is checked whenever Emacs waits for some kind of external
event (such as keyboard input, input from subprocesses, or a certain time);
if the program loops without waiting in any way, the timeout will not
be detected.
\n(fn (SECONDS TIMEOUT-FORMS...) BODY)"
(declare (indent 1) (debug ((form body) body)))
(let ((seconds (car list))
(timeout-forms (cdr list))
(timeout (make-symbol "timeout")))
`(let ((-with-timeout-value-
(catch ',timeout
(let* ((-with-timeout-timer-
(run-with-timer ,seconds nil
(lambda () (throw ',timeout ',timeout))))
(with-timeout-timers
(cons -with-timeout-timer- with-timeout-timers)))
(unwind-protect
(progn ,@body)
(cancel-timer -with-timeout-timer-))))))
;; It is tempting to avoid the `if' altogether and instead run
;; timeout-forms in the timer, just before throwing `timeout'.
;; But that would mean that timeout-forms are run in the deeper
;; dynamic context of the timer, with inhibit-quit set etc...
(if (eq -with-timeout-value- ',timeout)
(progn ,@timeout-forms)
-with-timeout-value-))))