diff options
| author | Eli Zaretskii | 2012-09-22 16:16:03 +0300 |
|---|---|---|
| committer | Eli Zaretskii | 2012-09-22 16:16:03 +0300 |
| commit | df9685f3961022245b9ab73b62023aa573862001 (patch) | |
| tree | dc572840dcc97dd6abe4a9cfe7e279525211a124 /src | |
| parent | 8e17c9ba1443c2f21c5801f0c4660ac08dccc837 (diff) | |
| download | emacs-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/ChangeLog | 9 | ||||
| -rw-r--r-- | src/keyboard.c | 34 |
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 @@ | |||
| 1 | 2012-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 | |||
| 1 | 2012-09-22 Martin Rudalics <rudalics@gmx.at> | 10 | 2012-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 | ||
| 4335 | static EMACS_TIME | 4335 | static EMACS_TIME |
| 4336 | timer_check_2 (void) | 4336 | timer_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 | |||
| 4500 | timer_check (void) | 4493 | timer_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 | ||