summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/ChangeLog8
-rw-r--r--src/atimer.c27
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 <dmantipov@yandex.ru>
+
+ * 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 <eggert@cs.ucla.edu>
* 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 <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#ifdef HAVE_TIMERFD
+#include <errno.h>
# include <sys/timerfd.h>
#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)
{