emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

sit-for and idle timers


From: Noah Friedman
Subject: sit-for and idle timers
Date: Fri, 11 Aug 2006 12:48:41 -0700 (PDT)

The change to sit-for of 2006-07-26 ("Use new SECONDS arg of read-event
instead of a timer") seems to cause problems with idle-timers
which call sit-for.

The problem is that read-event's call tree ultimately results in calling
keyboard.c:read_char, which calls timer_start_idle.  This resets the
activation time for all the current idle timer events, which means that any
function on an idle timer which calls sit-for is now getting scheduled to
be run recursively if another interval of the appropriate length ensues.  I
imagine this can continue until max-lisp-eval-depth is reached.

Here's a small test case which demonstrates the problem:

    (defvar itimer-test-wait 0.5)
    (defvar itimer-test-depth 0)

    (defun itimer-test ()
      (setq itimer-test-depth (1+ itimer-test-depth))
      (unwind-protect
          (let ((flag nil))
            (while (sit-for itimer-test-wait)
              (setq flag (not flag))
              (message "itimer-test-depth: %-3d%s"
                       itimer-test-depth
                       (if flag " (blink)" ""))))
        (setq itimer-test-depth (1- itimer-test-depth))
        (message "itimer-test-depth: %d" itimer-test-depth)))

    (run-with-idle-timer 0.25 t 'itimer-test)

In the pre-7/26 implementation, this timer should never print a depth
greater than 1, and the "(blink)" text should blink on and off with a
regular rhythm.

In the post-7/26 implementation, itimer-test-depth increments indefinitely
until an event is read.

One solution to this problem is to bind timer-idle-list to nil while
calling read-event.  I tested this trivially with a small defadvice:

    (defadvice read-event (around idlefrob activate)
      (let ((timer-idle-list nil))
        ad-do-it))

I'm not sure if this (binding the variable in sit-for that is, not the use
of defadvice as a temporary kludge) is the correct solution since it will
preempt the activation of other idle timers.  But it's simple.  The less
simple solution is probably for sit-for to go back to using a timer itself.

Thoughts?




reply via email to

[Prev in Thread] Current Thread [Next in Thread]