aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2012-09-22 16:16:03 +0300
committerEli Zaretskii2012-09-22 16:16:03 +0300
commitdf9685f3961022245b9ab73b62023aa573862001 (patch)
treedc572840dcc97dd6abe4a9cfe7e279525211a124
parent8e17c9ba1443c2f21c5801f0c4660ac08dccc837 (diff)
downloademacs-df9685f3961022245b9ab73b62023aa573862001.tar.gz
emacs-df9685f3961022245b9ab73b62023aa573862001.zip
Fix bugs #12447 and #12326 with infloop causes by idle timers, update docs.
src/keyboard.c (timer_check_2): Move calculation of 'timers' and 'idle_timers' from here ... (timer_check): ... to here. Use Fcopy_sequence to copy the timer lists, to avoid infloops when the timer does something stupid, like reinvoke itself with the same or smaller time-out. lisp/emacs-lisp/timer.el (run-with-idle-timer) (timer-activate-when-idle): Warn against reinvoking an idle timer from within its own timer action. doc/lispref/os.texi (Idle Timers): Warn against reinvoking an idle timer from within its own timer action.
-rw-r--r--doc/lispref/ChangeLog5
-rw-r--r--doc/lispref/os.texi7
-rw-r--r--lisp/ChangeLog6
-rw-r--r--lisp/emacs-lisp/timer.el15
-rw-r--r--src/ChangeLog9
-rw-r--r--src/keyboard.c34
6 files changed, 61 insertions, 15 deletions
diff --git a/doc/lispref/ChangeLog b/doc/lispref/ChangeLog
index f1ae632267b..8acd12d82a8 100644
--- a/doc/lispref/ChangeLog
+++ b/doc/lispref/ChangeLog
@@ -1,3 +1,8 @@
12012-09-22 Eli Zaretskii <eliz@gnu.org>
2
3 * os.texi (Idle Timers): Warn against reinvoking an idle timer
4 from within its own timer action. (Bug#12447)
5
12012-09-22 Chong Yidong <cyd@gnu.org> 62012-09-22 Chong Yidong <cyd@gnu.org>
2 7
3 * frames.texi (Pop-Up Menus): Minor clarification (Bug#11148). 8 * frames.texi (Pop-Up Menus): Minor clarification (Bug#11148).
diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index 6431ac8bead..68e53c78972 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1864,6 +1864,13 @@ It blocks out any idle timers that ought to run during that time.
1864@end itemize 1864@end itemize
1865 1865
1866@noindent 1866@noindent
1867For similar reasons, do not write an idle timer function that sets
1868up another idle time (including the same idle timer) with the
1869@var{secs} argument less or equal to the current idleness time. Such
1870a timer will run almost immediately, and continue running again and
1871again, instead of waiting for the next time Emacs becomes idle.
1872
1873@noindent
1867The correct approach is for the idle timer to reschedule itself after 1874The correct approach is for the idle timer to reschedule itself after
1868a brief pause, using the method in the @code{timer-function} example 1875a brief pause, using the method in the @code{timer-function} example
1869above. 1876above.
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index f18bfd73611..b0e91b675a3 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,9 @@
12012-09-22 Eli Zaretskii <eliz@gnu.org>
2
3 * emacs-lisp/timer.el (run-with-idle-timer)
4 (timer-activate-when-idle): Warn against reinvoking an idle timer
5 from within its own timer action. (Bug#12447)
6
12012-09-22 Martin Rudalics <rudalics@gmx.at> 72012-09-22 Martin Rudalics <rudalics@gmx.at>
2 8
3 * cus-start.el (window-combination-limit): Add new optional 9 * cus-start.el (window-combination-limit): Add new optional
diff --git a/lisp/emacs-lisp/timer.el b/lisp/emacs-lisp/timer.el
index 2248dde8c03..bcd582a6f88 100644
--- a/lisp/emacs-lisp/timer.el
+++ b/lisp/emacs-lisp/timer.el
@@ -205,12 +205,19 @@ timers). If nil, allocate a new cell."
205 "Insert TIMER into `timer-idle-list'. 205 "Insert TIMER into `timer-idle-list'.
206This arranges to activate TIMER whenever Emacs is next idle. 206This arranges to activate TIMER whenever Emacs is next idle.
207If optional argument DONT-WAIT is non-nil, set TIMER to activate 207If optional argument DONT-WAIT is non-nil, set TIMER to activate
208immediately, or at the right time, if Emacs is already idle. 208immediately \(see beloe\), or at the right time, if Emacs is
209already idle.
209 210
210REUSE-CELL, if non-nil, is a cons cell to reuse when inserting 211REUSE-CELL, if non-nil, is a cons cell to reuse when inserting
211TIMER into `timer-idle-list' (usually a cell removed from that 212TIMER into `timer-idle-list' (usually a cell removed from that
212list by `cancel-timer-internal'; using this reduces consing for 213list by `cancel-timer-internal'; using this reduces consing for
213repeat timers). If nil, allocate a new cell." 214repeat timers). If nil, allocate a new cell.
215
216Using non-nil DONT-WAIT is not recommended when activating an
217idle timer from an idle timer handler, if the timer being
218activated has an idleness time that is smaller or equal to
219the time of the current timer. That's because the activated
220timer will fire right away."
214 (timer--activate timer (not dont-wait) reuse-cell 'idle)) 221 (timer--activate timer (not dont-wait) reuse-cell 'idle))
215 222
216(defalias 'disable-timeout 'cancel-timer) 223(defalias 'disable-timeout 'cancel-timer)
@@ -403,7 +410,9 @@ The action is to call FUNCTION with arguments ARGS.
403SECS may be an integer, a floating point number, or the internal 410SECS may be an integer, a floating point number, or the internal
404time format returned by, e.g., `current-idle-time'. 411time format returned by, e.g., `current-idle-time'.
405If Emacs is currently idle, and has been idle for N seconds (N < SECS), 412If Emacs is currently idle, and has been idle for N seconds (N < SECS),
406then it will call FUNCTION in SECS - N seconds from now. 413then it will call FUNCTION in SECS - N seconds from now. Using
414SECS <= N is not recommended if this function is invoked from an idle
415timer, because FUNCTION will then be called immediately.
407 416
408If REPEAT is non-nil, do the action each time Emacs has been idle for 417If REPEAT is non-nil, do the action each time Emacs has been idle for
409exactly SECS seconds (that is, only once for each time Emacs becomes idle). 418exactly SECS seconds (that is, only once for each time Emacs becomes idle).
diff --git a/src/ChangeLog b/src/ChangeLog
index 6ea40b3f122..b69d4bb7113 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,12 @@
12012-09-22 Eli Zaretskii <eliz@gnu.org>
2
3 * keyboard.c (timer_check_2): Move calculation of 'timers' and
4 'idle_timers' from here ...
5 (timer_check): ... to here. Use Fcopy_sequence to copy the timer
6 lists, to avoid infloops when the timer does something stupid,
7 like reinvoke itself with the same or smaller time-out.
8 (Bug#12447)
9
12012-09-22 Martin Rudalics <rudalics@gmx.at> 102012-09-22 Martin Rudalics <rudalics@gmx.at>
2 11
3 * window.c (Fsplit_window_internal): Handle only Qt value of 12 * window.c (Fsplit_window_internal): Handle only Qt value of
diff --git a/src/keyboard.c b/src/keyboard.c
index 098d3530ef8..8b1113a026a 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -4333,25 +4333,18 @@ decode_timer (Lisp_Object timer, EMACS_TIME *result)
4333 should be done. */ 4333 should be done. */
4334 4334
4335static EMACS_TIME 4335static EMACS_TIME
4336timer_check_2 (void) 4336timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
4337{ 4337{
4338 EMACS_TIME nexttime; 4338 EMACS_TIME nexttime;
4339 EMACS_TIME now; 4339 EMACS_TIME now;
4340 EMACS_TIME idleness_now; 4340 EMACS_TIME idleness_now;
4341 Lisp_Object timers, idle_timers, chosen_timer; 4341 Lisp_Object chosen_timer;
4342 struct gcpro gcpro1, gcpro2, gcpro3; 4342 struct gcpro gcpro1;
4343 4343
4344 nexttime = invalid_emacs_time (); 4344 nexttime = invalid_emacs_time ();
4345 4345
4346 /* Always consider the ordinary timers. */
4347 timers = Vtimer_list;
4348 /* Consider the idle timers only if Emacs is idle. */
4349 if (EMACS_TIME_VALID_P (timer_idleness_start_time))
4350 idle_timers = Vtimer_idle_list;
4351 else
4352 idle_timers = Qnil;
4353 chosen_timer = Qnil; 4346 chosen_timer = Qnil;
4354 GCPRO3 (timers, idle_timers, chosen_timer); 4347 GCPRO1 (chosen_timer);
4355 4348
4356 /* First run the code that was delayed. */ 4349 /* First run the code that was delayed. */
4357 while (CONSP (pending_funcalls)) 4350 while (CONSP (pending_funcalls))
@@ -4500,13 +4493,30 @@ EMACS_TIME
4500timer_check (void) 4493timer_check (void)
4501{ 4494{
4502 EMACS_TIME nexttime; 4495 EMACS_TIME nexttime;
4496 Lisp_Object timers, idle_timers;
4497 struct gcpro gcpro1, gcpro2;
4498
4499 /* We use copies of the timers' lists to allow a timer to add itself
4500 again, without locking up Emacs if the newly added timer is
4501 already ripe when added. */
4502
4503 /* Always consider the ordinary timers. */
4504 timers = Fcopy_sequence (Vtimer_list);
4505 /* Consider the idle timers only if Emacs is idle. */
4506 if (EMACS_TIME_VALID_P (timer_idleness_start_time))
4507 idle_timers = Fcopy_sequence (Vtimer_idle_list);
4508 else
4509 idle_timers = Qnil;
4510
4511 GCPRO2 (timers, idle_timers);
4503 4512
4504 do 4513 do
4505 { 4514 {
4506 nexttime = timer_check_2 (); 4515 nexttime = timer_check_2 (timers, idle_timers);
4507 } 4516 }
4508 while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0); 4517 while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
4509 4518
4519 UNGCPRO;
4510 return nexttime; 4520 return nexttime;
4511} 4521}
4512 4522