aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMattias EngdegÄrd2022-05-30 12:25:19 +0200
committerMattias EngdegÄrd2022-05-30 15:52:02 +0200
commit169797a3002fae1e86ee799475cd4f1b7ef9a3d1 (patch)
tree10a3b1f0b2509520dc4839e41f8d112317377f33 /src
parent78e8893f5d4b1c9ca5742fbe20bc5d05a843ed4e (diff)
downloademacs-169797a3002fae1e86ee799475cd4f1b7ef9a3d1.tar.gz
emacs-169797a3002fae1e86ee799475cd4f1b7ef9a3d1.zip
Fix atimer setting and overdue expiration (bug#55628)
* src/atimer.c (set_alarm): If the atimer has already expired, signal it right away instead of postponing it further. Previously this could occur repeatedly, blocking atimers indefinitely. Also only use `alarm` as fallback if `setitimer` is unavailable, not both at the same time (which makes no sense, and they both typically use the same mechanism behind the curtains). * test/src/eval-tests.el (eval-tests/funcall-with-delayed-message): New test, verifying proper functioning of funcall-with-delayed-message which also serves as test for this bug (which also caused debug-timer-check to fail, but that test is only run when Emacs is built with enable-checking).
Diffstat (limited to 'src')
-rw-r--r--src/atimer.c33
1 files changed, 16 insertions, 17 deletions
diff --git a/src/atimer.c b/src/atimer.c
index 1c6c881fc02..c26904e1f01 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -297,11 +297,6 @@ set_alarm (void)
297{ 297{
298 if (atimers) 298 if (atimers)
299 { 299 {
300#ifdef HAVE_SETITIMER
301 struct itimerval it;
302#endif
303 struct timespec now, interval;
304
305#ifdef HAVE_ITIMERSPEC 300#ifdef HAVE_ITIMERSPEC
306 if (0 <= timerfd || alarm_timer_ok) 301 if (0 <= timerfd || alarm_timer_ok)
307 { 302 {
@@ -337,20 +332,24 @@ set_alarm (void)
337 } 332 }
338#endif 333#endif
339 334
340 /* Determine interval till the next timer is ripe. 335 /* Determine interval till the next timer is ripe. */
341 Don't set the interval to 0; this disables the timer. */ 336 struct timespec now = current_timespec ();
342 now = current_timespec (); 337 if (timespec_cmp (atimers->expiration, now) <= 0)
343 interval = (timespec_cmp (atimers->expiration, now) <= 0 338 {
344 ? make_timespec (0, 1000 * 1000) 339 /* Timer is (over)due -- just trigger the signal right way. */
345 : timespec_sub (atimers->expiration, now)); 340 raise (SIGALRM);
341 }
342 else
343 {
344 struct timespec interval = timespec_sub (atimers->expiration, now);
346 345
347#ifdef HAVE_SETITIMER 346#ifdef HAVE_SETITIMER
348 347 struct itimerval it = {.it_value = make_timeval (interval)};
349 memset (&it, 0, sizeof it); 348 setitimer (ITIMER_REAL, &it, 0);
350 it.it_value = make_timeval (interval); 349#else
351 setitimer (ITIMER_REAL, &it, 0); 350 alarm (max (interval.tv_sec, 1));
352#endif /* not HAVE_SETITIMER */ 351#endif
353 alarm (max (interval.tv_sec, 1)); 352 }
354 } 353 }
355} 354}
356 355