aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2012-09-22 16:16:03 +0300
committerEli Zaretskii2012-09-22 16:16:03 +0300
commitdf9685f3961022245b9ab73b62023aa573862001 (patch)
treedc572840dcc97dd6abe4a9cfe7e279525211a124 /src
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.
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog9
-rw-r--r--src/keyboard.c34
2 files changed, 31 insertions, 12 deletions
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