From 11804a04ada37cbf33576a5a69189bd43b3d66dd Mon Sep 17 00:00:00 2001 From: Dmitry Antipov Date: Fri, 1 Aug 2014 10:52:02 +0400 Subject: [PATCH] * atimer.c (toplevel) [HAVE_TIMERFD]: Include errno.h. (timerfd_callback): Ignore weird events with no data. Add tight assertions and comments. (init_atimer) [HAVE_TIMERFD]: Add environment variable to optionally disabletimerfd-based timer. Use TFD_NONBLOCK for timer descriptor. --- src/ChangeLog | 8 ++++++++ src/atimer.c | 27 +++++++++++++++++++++------ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 9dbd7c97a53..a0ac451f35b 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2014-08-01 Dmitry Antipov + + * atimer.c (toplevel) [HAVE_TIMERFD]: Include errno.h. + (timerfd_callback): Ignore weird events with no data. Add tight + assertions and comments. + (init_atimer) [HAVE_TIMERFD]: Add environment variable to optionally + disable timerfd-based timer. Use TFD_NONBLOCK for timer descriptor. + 2014-08-01 Paul Eggert * frame.c (x_set_frame_parameters): Fix typo in previous patch. diff --git a/src/atimer.c b/src/atimer.c index daac32f19b4..ce782f6adb6 100644 --- a/src/atimer.c +++ b/src/atimer.c @@ -27,6 +27,7 @@ along with GNU Emacs. If not, see . */ #include #ifdef HAVE_TIMERFD +#include # include #endif @@ -399,14 +400,26 @@ handle_alarm_signal (int sig) void timerfd_callback (int fd, void *arg) { - char buf[8]; ptrdiff_t nbytes; + uint64_t expirations; eassert (fd == timerfd); - nbytes = emacs_read (fd, buf, sizeof (buf)); - /* Just discard an expiration count for now. */ - eassert (nbytes == sizeof (buf)); - do_pending_atimers (); + nbytes = emacs_read (fd, &expirations, sizeof (expirations)); + + if (nbytes == sizeof (expirations)) + { + /* Timer should expire just once. */ + eassert (expirations == 1); + do_pending_atimers (); + } + else if (nbytes < 0) + /* For some not yet known reason, we may get weird event and no + data on timer descriptor. This can break Gnus at least, see: + http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00503.html. */ + eassert (errno == EAGAIN); + else + /* I don't know what else can happen with this descriptor. */ + emacs_abort (); } #endif /* HAVE_TIMERFD */ @@ -528,7 +541,9 @@ init_atimer (void) { #ifdef HAVE_ITIMERSPEC # ifdef HAVE_TIMERFD - timerfd = timerfd_create (CLOCK_REALTIME, TFD_CLOEXEC); + /* Until this feature is considered stable, you can ask to not use it. */ + timerfd = (egetenv ("EMACS_IGNORE_TIMERFD") ? -1 : + timerfd_create (CLOCK_REALTIME, TFD_NONBLOCK | TFD_CLOEXEC)); # endif if (timerfd < 0) { -- 2.39.5