diff options
author | Stefan Monnier <monnier@iro.umontreal.ca> | 2014-05-18 08:58:30 -0400 |
---|---|---|
committer | Stefan Monnier <monnier@iro.umontreal.ca> | 2014-05-18 08:58:30 -0400 |
commit | 08a2434e2f7a60fc558e052e37409333582504cb (patch) | |
tree | 0fdc023b08f78ad8fbd3950777fdf52e389fb298 /lisp/emacs-lisp/timer.el | |
parent | 2f826609630cc1bf1d470428273711ebde9eec3c (diff) | |
download | emacs-08a2434e2f7a60fc558e052e37409333582504cb.tar.gz emacs-08a2434e2f7a60fc558e052e37409333582504cb.tar.bz2 emacs-08a2434e2f7a60fc558e052e37409333582504cb.zip |
* lisp/emacs-lisp/timer.el (timer-event-handler): Don't run if canceled.
Fixes: debbugs:17392
Diffstat (limited to 'lisp/emacs-lisp/timer.el')
-rw-r--r-- | lisp/emacs-lisp/timer.el | 80 |
1 files changed, 44 insertions, 36 deletions
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el index 515bbc36a06..516ea3643d5 100644 --- a/lisp/emacs-lisp/timer.el +++ b/lisp/emacs-lisp/timer.el @@ -290,42 +290,50 @@ This function is called, by name, directly by the C code." (cell ;; Delete from queue. Record the cons cell that was used. (cancel-timer-internal timer))) - ;; Re-schedule if requested. - (if (timer--repeat-delay timer) - (if (timer--idle-delay timer) - (timer-activate-when-idle timer nil cell) - (timer-inc-time timer (timer--repeat-delay timer) 0) - ;; If real time has jumped forward, - ;; perhaps because Emacs was suspended for a long time, - ;; limit how many times things get repeated. - (if (and (numberp timer-max-repeats) - (< 0 (timer-until timer (current-time)))) - (let ((repeats (/ (timer-until timer (current-time)) - (timer--repeat-delay timer)))) - (if (> repeats timer-max-repeats) - (timer-inc-time timer (* (timer--repeat-delay timer) - repeats))))) - ;; Place it back on the timer-list before running - ;; timer--function, so it can cancel-timer itself. - (timer-activate timer t cell) - (setq retrigger t))) - ;; Run handler. - (condition-case-unless-debug err - ;; Timer functions should not change the current buffer. - ;; If they do, all kinds of nasty surprises can happen, - ;; and it can be hellish to track down their source. - (save-current-buffer - (apply (timer--function timer) (timer--args timer))) - (error (message "Error running timer%s: %S" - (if (symbolp (timer--function timer)) - (format " `%s'" (timer--function timer)) "") - err))) - (when (and retrigger - ;; If the timer's been canceled, don't "retrigger" it - ;; since it might still be in the copy of timer-list kept - ;; by keyboard.c:timer_check (bug#14156). - (memq timer timer-list)) - (setf (timer--triggered timer) nil))))) + ;; If `cell' is nil, it means the timer was already canceled, so we + ;; shouldn't be running it at all. This can happen for example with the + ;; following scenario (bug#17392): + ;; - we run timers, starting with A (and remembering the rest as (B C)). + ;; - A runs and a does a sit-for. + ;; - during sit-for we run timer D which cancels timer B. + ;; - timer A finally finishes, so we move on to timers B and C. + (unless cell + ;; Re-schedule if requested. + (if (timer--repeat-delay timer) + (if (timer--idle-delay timer) + (timer-activate-when-idle timer nil cell) + (timer-inc-time timer (timer--repeat-delay timer) 0) + ;; If real time has jumped forward, + ;; perhaps because Emacs was suspended for a long time, + ;; limit how many times things get repeated. + (if (and (numberp timer-max-repeats) + (< 0 (timer-until timer (current-time)))) + (let ((repeats (/ (timer-until timer (current-time)) + (timer--repeat-delay timer)))) + (if (> repeats timer-max-repeats) + (timer-inc-time timer (* (timer--repeat-delay timer) + repeats))))) + ;; Place it back on the timer-list before running + ;; timer--function, so it can cancel-timer itself. + (timer-activate timer t cell) + (setq retrigger t))) + ;; Run handler. + (condition-case-unless-debug err + ;; Timer functions should not change the current buffer. + ;; If they do, all kinds of nasty surprises can happen, + ;; and it can be hellish to track down their source. + (save-current-buffer + (apply (timer--function timer) (timer--args timer))) + (error (message "Error running timer%s: %S" + (if (symbolp (timer--function timer)) + (format " `%s'" (timer--function timer)) "") + err))) + (when (and retrigger + ;; If the timer's been canceled, don't "retrigger" it + ;; since it might still be in the copy of timer-list kept + ;; by keyboard.c:timer_check (bug#14156). + (memq timer timer-list)) + (setf (timer--triggered timer) nil)))))) ;; This function is incompatible with the one in levents.el. (defun timeout-event-p (event) |