1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-05 22:20:24 -08:00

Improve timer robustness by protecting pending function calls

* src/keyboard.c (timer_check_2): Protect pending function calls with
inhibit-quit and deactivate-mark bindings, same as timer callbacks.
Also use specbind for deactivate-mark in timer handler for consistency.
This commit is contained in:
Daniel Colascione 2025-06-10 11:39:19 -07:00
parent da92ad2eaa
commit 57b5be4eb9

View file

@ -4708,6 +4708,14 @@ static struct timespec
timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers) timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
{ {
/* First run the code that was delayed. */ /* First run the code that was delayed. */
if (CONSP (pending_funcalls))
{
/* safe_calln eats signals but doesn't block quit per se. Do it
here so C-g doesn't end execution of pending function calls
prematurely. */
specpdl_ref count = SPECPDL_INDEX ();
specbind (Qinhibit_quit, Qt);
specbind (Qdeactivate_mark, Vdeactivate_mark);
while (CONSP (pending_funcalls)) while (CONSP (pending_funcalls))
{ {
Lisp_Object funcall = XCAR (pending_funcalls); Lisp_Object funcall = XCAR (pending_funcalls);
@ -4715,6 +4723,9 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
safe_calln (Qapply, XCAR (funcall), XCDR (funcall)); safe_calln (Qapply, XCAR (funcall), XCDR (funcall));
} }
unbind_to (count, Qnil);
}
if (! (CONSP (timers) || CONSP (idle_timers))) if (! (CONSP (timers) || CONSP (idle_timers)))
return invalid_timespec (); return invalid_timespec ();
@ -4811,7 +4822,7 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
if (NILP (AREF (chosen_timer, 0))) if (NILP (AREF (chosen_timer, 0)))
{ {
specpdl_ref count = SPECPDL_INDEX (); specpdl_ref count = SPECPDL_INDEX ();
Lisp_Object old_deactivate_mark = Vdeactivate_mark; specbind (Qdeactivate_mark, Vdeactivate_mark);
/* Mark the timer as triggered to prevent problems if the lisp /* Mark the timer as triggered to prevent problems if the lisp
code fails to reschedule it right. */ code fails to reschedule it right. */
@ -4820,7 +4831,6 @@ timer_check_2 (Lisp_Object timers, Lisp_Object idle_timers)
specbind (Qinhibit_quit, Qt); specbind (Qinhibit_quit, Qt);
calln (Qtimer_event_handler, chosen_timer); calln (Qtimer_event_handler, chosen_timer);
Vdeactivate_mark = old_deactivate_mark;
timers_run++; timers_run++;
unbind_to (count, Qnil); unbind_to (count, Qnil);