summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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 @@
+2012-09-22 Eli Zaretskii <eliz@gnu.org>
+
+ * 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.
+ (Bug#12447)
+
2012-09-22 Martin Rudalics <rudalics@gmx.at>
* 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)
should be done. */
static EMACS_TIME
-timer_check_2 (void)
+timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{
EMACS_TIME nexttime;
EMACS_TIME now;
EMACS_TIME idleness_now;
- Lisp_Object timers, idle_timers, chosen_timer;
- struct gcpro gcpro1, gcpro2, gcpro3;
+ Lisp_Object chosen_timer;
+ struct gcpro gcpro1;
nexttime = invalid_emacs_time ();
- /* Always consider the ordinary timers. */
- timers = Vtimer_list;
- /* Consider the idle timers only if Emacs is idle. */
- if (EMACS_TIME_VALID_P (timer_idleness_start_time))
- idle_timers = Vtimer_idle_list;
- else
- idle_timers = Qnil;
chosen_timer = Qnil;
- GCPRO3 (timers, idle_timers, chosen_timer);
+ GCPRO1 (chosen_timer);
/* First run the code that was delayed. */
while (CONSP (pending_funcalls))
@@ -4500,13 +4493,30 @@ EMACS_TIME
timer_check (void)
{
EMACS_TIME nexttime;
+ Lisp_Object timers, idle_timers;
+ struct gcpro gcpro1, gcpro2;
+
+ /* We use copies of the timers' lists to allow a timer to add itself
+ again, without locking up Emacs if the newly added timer is
+ already ripe when added. */
+
+ /* Always consider the ordinary timers. */
+ timers = Fcopy_sequence (Vtimer_list);
+ /* Consider the idle timers only if Emacs is idle. */
+ if (EMACS_TIME_VALID_P (timer_idleness_start_time))
+ idle_timers = Fcopy_sequence (Vtimer_idle_list);
+ else
+ idle_timers = Qnil;
+
+ GCPRO2 (timers, idle_timers);
do
{
- nexttime = timer_check_2 ();
+ nexttime = timer_check_2 (timers, idle_timers);
}
while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
+ UNGCPRO;
return nexttime;
}