mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-06 11:50:51 -08:00
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.
This commit is contained in:
parent
8e17c9ba14
commit
df9685f396
6 changed files with 61 additions and 15 deletions
|
|
@ -1,3 +1,8 @@
|
||||||
|
2012-09-22 Eli Zaretskii <eliz@gnu.org>
|
||||||
|
|
||||||
|
* os.texi (Idle Timers): Warn against reinvoking an idle timer
|
||||||
|
from within its own timer action. (Bug#12447)
|
||||||
|
|
||||||
2012-09-22 Chong Yidong <cyd@gnu.org>
|
2012-09-22 Chong Yidong <cyd@gnu.org>
|
||||||
|
|
||||||
* frames.texi (Pop-Up Menus): Minor clarification (Bug#11148).
|
* frames.texi (Pop-Up Menus): Minor clarification (Bug#11148).
|
||||||
|
|
|
||||||
|
|
@ -1863,6 +1863,13 @@ only while waiting).
|
||||||
It blocks out any idle timers that ought to run during that time.
|
It blocks out any idle timers that ought to run during that time.
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
|
@noindent
|
||||||
|
For similar reasons, do not write an idle timer function that sets
|
||||||
|
up another idle time (including the same idle timer) with the
|
||||||
|
@var{secs} argument less or equal to the current idleness time. Such
|
||||||
|
a timer will run almost immediately, and continue running again and
|
||||||
|
again, instead of waiting for the next time Emacs becomes idle.
|
||||||
|
|
||||||
@noindent
|
@noindent
|
||||||
The correct approach is for the idle timer to reschedule itself after
|
The correct approach is for the idle timer to reschedule itself after
|
||||||
a brief pause, using the method in the @code{timer-function} example
|
a brief pause, using the method in the @code{timer-function} example
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
|
2012-09-22 Eli Zaretskii <eliz@gnu.org>
|
||||||
|
|
||||||
|
* emacs-lisp/timer.el (run-with-idle-timer)
|
||||||
|
(timer-activate-when-idle): Warn against reinvoking an idle timer
|
||||||
|
from within its own timer action. (Bug#12447)
|
||||||
|
|
||||||
2012-09-22 Martin Rudalics <rudalics@gmx.at>
|
2012-09-22 Martin Rudalics <rudalics@gmx.at>
|
||||||
|
|
||||||
* cus-start.el (window-combination-limit): Add new optional
|
* cus-start.el (window-combination-limit): Add new optional
|
||||||
|
|
|
||||||
|
|
@ -205,12 +205,19 @@ timers). If nil, allocate a new cell."
|
||||||
"Insert TIMER into `timer-idle-list'.
|
"Insert TIMER into `timer-idle-list'.
|
||||||
This arranges to activate TIMER whenever Emacs is next idle.
|
This arranges to activate TIMER whenever Emacs is next idle.
|
||||||
If optional argument DONT-WAIT is non-nil, set TIMER to activate
|
If optional argument DONT-WAIT is non-nil, set TIMER to activate
|
||||||
immediately, or at the right time, if Emacs is already idle.
|
immediately \(see beloe\), or at the right time, if Emacs is
|
||||||
|
already idle.
|
||||||
|
|
||||||
REUSE-CELL, if non-nil, is a cons cell to reuse when inserting
|
REUSE-CELL, if non-nil, is a cons cell to reuse when inserting
|
||||||
TIMER into `timer-idle-list' (usually a cell removed from that
|
TIMER into `timer-idle-list' (usually a cell removed from that
|
||||||
list by `cancel-timer-internal'; using this reduces consing for
|
list by `cancel-timer-internal'; using this reduces consing for
|
||||||
repeat timers). If nil, allocate a new cell."
|
repeat timers). If nil, allocate a new cell.
|
||||||
|
|
||||||
|
Using non-nil DONT-WAIT is not recommended when activating an
|
||||||
|
idle timer from an idle timer handler, if the timer being
|
||||||
|
activated has an idleness time that is smaller or equal to
|
||||||
|
the time of the current timer. That's because the activated
|
||||||
|
timer will fire right away."
|
||||||
(timer--activate timer (not dont-wait) reuse-cell 'idle))
|
(timer--activate timer (not dont-wait) reuse-cell 'idle))
|
||||||
|
|
||||||
(defalias 'disable-timeout 'cancel-timer)
|
(defalias 'disable-timeout 'cancel-timer)
|
||||||
|
|
@ -403,7 +410,9 @@ The action is to call FUNCTION with arguments ARGS.
|
||||||
SECS may be an integer, a floating point number, or the internal
|
SECS may be an integer, a floating point number, or the internal
|
||||||
time format returned by, e.g., `current-idle-time'.
|
time format returned by, e.g., `current-idle-time'.
|
||||||
If Emacs is currently idle, and has been idle for N seconds (N < SECS),
|
If Emacs is currently idle, and has been idle for N seconds (N < SECS),
|
||||||
then it will call FUNCTION in SECS - N seconds from now.
|
then it will call FUNCTION in SECS - N seconds from now. Using
|
||||||
|
SECS <= N is not recommended if this function is invoked from an idle
|
||||||
|
timer, because FUNCTION will then be called immediately.
|
||||||
|
|
||||||
If REPEAT is non-nil, do the action each time Emacs has been idle for
|
If REPEAT is non-nil, do the action each time Emacs has been idle for
|
||||||
exactly SECS seconds (that is, only once for each time Emacs becomes idle).
|
exactly SECS seconds (that is, only once for each time Emacs becomes idle).
|
||||||
|
|
|
||||||
|
|
@ -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>
|
2012-09-22 Martin Rudalics <rudalics@gmx.at>
|
||||||
|
|
||||||
* window.c (Fsplit_window_internal): Handle only Qt value of
|
* window.c (Fsplit_window_internal): Handle only Qt value of
|
||||||
|
|
|
||||||
|
|
@ -4333,25 +4333,18 @@ decode_timer (Lisp_Object timer, EMACS_TIME *result)
|
||||||
should be done. */
|
should be done. */
|
||||||
|
|
||||||
static EMACS_TIME
|
static EMACS_TIME
|
||||||
timer_check_2 (void)
|
timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
|
||||||
{
|
{
|
||||||
EMACS_TIME nexttime;
|
EMACS_TIME nexttime;
|
||||||
EMACS_TIME now;
|
EMACS_TIME now;
|
||||||
EMACS_TIME idleness_now;
|
EMACS_TIME idleness_now;
|
||||||
Lisp_Object timers, idle_timers, chosen_timer;
|
Lisp_Object chosen_timer;
|
||||||
struct gcpro gcpro1, gcpro2, gcpro3;
|
struct gcpro gcpro1;
|
||||||
|
|
||||||
nexttime = invalid_emacs_time ();
|
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;
|
chosen_timer = Qnil;
|
||||||
GCPRO3 (timers, idle_timers, chosen_timer);
|
GCPRO1 (chosen_timer);
|
||||||
|
|
||||||
/* First run the code that was delayed. */
|
/* First run the code that was delayed. */
|
||||||
while (CONSP (pending_funcalls))
|
while (CONSP (pending_funcalls))
|
||||||
|
|
@ -4500,13 +4493,30 @@ EMACS_TIME
|
||||||
timer_check (void)
|
timer_check (void)
|
||||||
{
|
{
|
||||||
EMACS_TIME nexttime;
|
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
|
do
|
||||||
{
|
{
|
||||||
nexttime = timer_check_2 ();
|
nexttime = timer_check_2 (timers, idle_timers);
|
||||||
}
|
}
|
||||||
while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
|
while (EMACS_SECS (nexttime) == 0 && EMACS_NSECS (nexttime) == 0);
|
||||||
|
|
||||||
|
UNGCPRO;
|
||||||
return nexttime;
|
return nexttime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue