From 2daa203c3eb983433b86b841bf31d3e91bb51ab4 Mon Sep 17 00:00:00 2001
From: Dmitry Antipov <dmantipov@yandex.ru>
Date: Mon, 28 Jul 2014 18:50:55 +0400
Subject: [PATCH] Fix Gnus-related issues reported by David Kastrup
 <dak@gnu.org> in
 <http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00370.html>. *
 atimer.c (timerfd_callback): Always read expiration data. Add comment.
 (turn_on_atimers) [HAVE_TIMERFD]: Disarm timerfd timer. * process.c
 (add_timer_wait_descriptor): Add timer descriptor to input_wait_mask and
 non_process_wait_mask as well.

---
 src/ChangeLog |  8 ++++++++
 src/atimer.c  | 23 ++++++++++++++++++++++-
 src/process.c |  2 ++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/ChangeLog b/src/ChangeLog
index 57d49594d7a..0c79309609f 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -35,6 +35,14 @@
 	Define as no-op.
 	(adjust_frame_size): Always declare prototype.
 
+	Fix Gnus-related issues reported by David Kastrup <dak@gnu.org> in
+	<http://lists.gnu.org/archive/html/emacs-devel/2014-07/msg00370.html>.
+	* atimer.c (timerfd_callback): Always read expiration data.
+	Add comment.
+	(turn_on_atimers) [HAVE_TIMERFD]: Disarm timerfd timer.
+	* process.c (add_timer_wait_descriptor): Add timer descriptor
+	to input_wait_mask and non_process_wait_mask as well.
+
 2014-07-28  Paul Eggert  <eggert@cs.ucla.edu>
 
 	* frame.c (x_set_frame_parameters): Don't use uninitialized locals.
diff --git a/src/atimer.c b/src/atimer.c
index 9079e7712e0..c03ac96c6da 100644
--- a/src/atimer.c
+++ b/src/atimer.c
@@ -410,9 +410,19 @@ handle_alarm_signal (int sig)
 
 #ifdef HAVE_TIMERFD
 
+/* Called from wait_reading_process_output when FD, which
+   should be equal to TIMERFD, is available for reading.  */
+
 void
 timerfd_callback (int fd, void *arg)
 {
+  char buf[8];
+  ptrdiff_t nbytes;
+
+  eassert (fd == timerfd);
+  nbytes = emacs_read (fd, buf, sizeof (buf));
+  /* Just discard an expiration count for now.  */
+  eassert (nbytes == sizeof (buf));
   do_pending_atimers ();
 }
 
@@ -442,7 +452,18 @@ turn_on_atimers (bool on)
   if (on)
     set_alarm ();
   else
-    alarm (0);
+    {
+#ifdef HAVE_TIMERFD
+      if (special_timer_available > 1)
+	{
+	  struct itimerspec ispec;
+	  memset (&ispec, 0, sizeof (ispec));
+	  /* Writing zero expiration time should disarm it.  */
+	  timerfd_settime (timerfd, TFD_TIMER_ABSTIME, &ispec, 0);
+	}
+#endif /* HAVE_TIMERFD */
+      alarm (0);
+    }
 }
 
 /* This is intended to use from automated tests.  */
diff --git a/src/process.c b/src/process.c
index cfc1e189cab..f34be69864a 100644
--- a/src/process.c
+++ b/src/process.c
@@ -6835,7 +6835,9 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
 void
 add_timer_wait_descriptor (int fd)
 {
+  FD_SET (fd, &input_wait_mask);
   FD_SET (fd, &non_keyboard_wait_mask);
+  FD_SET (fd, &non_process_wait_mask);  
   fd_callback_info[fd].func = timerfd_callback;
   fd_callback_info[fd].data = NULL;
   fd_callback_info[fd].condition |= FOR_READ;
-- 
2.39.5