GNU bug report logs - #30368
‘select’ returns non-empty sets upon EINTR or EAGAIN

Previous Next

Package: guile;

Reported by: ludo <at> gnu.org (Ludovic Courtès)

Date: Tue, 6 Feb 2018 10:40:02 UTC

Severity: important

Done: ludo <at> gnu.org (Ludovic Courtès)

Bug is archived. No further changes may be made.

Full log


View this message in rfc822 format

From: help-debbugs <at> gnu.org (GNU bug Tracking System)
To: ludo <at> gnu.org (Ludovic Courtès)
Subject: bug#30368: closed (Re: bug#30368: ‘select’
 returns non-empty sets upon EINTR or EAGAIN)
Date: Fri, 16 Feb 2018 14:34:02 +0000
[Message part 1 (text/plain, inline)]
Your bug report

#30368: ‘select’ returns non-empty sets upon EINTR or EAGAIN

which was filed against the guile package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to 30368 <at> debbugs.gnu.org.

-- 
30368: http://debbugs.gnu.org/cgi/bugreport.cgi?bug=30368
GNU Bug Tracking System
Contact help-debbugs <at> gnu.org with problems
[Message part 2 (message/rfc822, inline)]
From: ludo <at> gnu.org (Ludovic Courtès)
To: 30368-done <at> debbugs.gnu.org
Subject: Re: bug#30368: ‘select’ returns non-empty sets
 upon EINTR or EAGAIN
Date: Fri, 16 Feb 2018 15:33:04 +0100
ludo <at> gnu.org (Ludovic Courtès) skribis:

> The attached patch fixes it by clearing the returned FD sets on
> EINTR/EAGAIN.

Pushed as f390afa0cc84eb84ed2cb3e03f542b991d4bb080.

Ludo’.

[Message part 3 (message/rfc822, inline)]
From: ludo <at> gnu.org (Ludovic Courtès)
To: bug-guile <at> gnu.org
Subject: ‘select’ returns non-empty sets upon EINTR or
 EAGAIN
Date: Tue, 06 Feb 2018 11:39:30 +0100
[Message part 4 (text/plain, inline)]
Hello,

As of Guile 2.2.3, the Scheme-level ‘select’ can return non-empty sets
when the C-level ‘select’ returns EINTR or EAGAIN.  The program below
illustrates this:

--8<---------------cut here---------------start------------->8---
(use-modules (ice-9 match))

(sigaction SIGINT (lambda args
                    (pk 'signal! args)))

(let ((target (getpid)))
  (match (primitive-fork)
    ((? zero?)
     (sleep 4)
     (kill target SIGINT)
     (primitive-exit 0))
    (_ #t)))

(match (select (list (current-input-port)) '() '())
  (((port) () ())
   (pk 'reading-from port)
   (read-char port))
  (lst
   (pk 'done lst)))
--8<---------------cut here---------------end--------------->8---

On 2.2.3, it prints:

--8<---------------cut here---------------start------------->8---
$ guile select.scm


;;; (signal! (2))
;;; (reading-from #<input: file /dev/pts/9>)
--8<---------------cut here---------------end--------------->8---

From there on it’s stuck in a read(0, …) call.

The attached patch fixes it by clearing the returned FD sets on
EINTR/EAGAIN.

(Besides it seems that select(2) never returns EAGAIN.)

I’m not sure how to write a test for this; the one above is
timing-sensitive, which wouldn’t be great.

Thoughts?

Ludo’.

[Message part 5 (text/x-patch, inline)]
diff --git a/libguile/filesys.c b/libguile/filesys.c
index e39dc4a0d..05dd2bd16 100644
--- a/libguile/filesys.c
+++ b/libguile/filesys.c
@@ -1,5 +1,5 @@
 /* Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2006,
- *   2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017 Free Software Foundation, Inc.
+ *   2009, 2010, 2011, 2012, 2013, 2014, 2016, 2017, 2018 Free Software Foundation, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public License
@@ -900,10 +900,20 @@ SCM_DEFINE (scm_select, "select", 3, 2, 0,
     int rv = scm_std_select (max_fd + 1,
                              &read_set, &write_set, &except_set,
                              time_ptr);
-    /* Let EINTR / EAGAIN cause a return to the user and let them loop
-       to run any asyncs that might be pending.  */
-    if (rv < 0 && errno != EINTR && errno != EAGAIN)
-      SCM_SYSERROR;
+    if (rv < 0)
+      {
+        /* Let EINTR / EAGAIN cause a return to the user and let them
+           loop to run any asyncs that might be pending.  */
+        if (errno != EINTR && errno != EAGAIN)
+          SCM_SYSERROR;
+        else
+          {
+            /* Return empty sets.  */
+            FD_ZERO (&read_set);
+            FD_ZERO (&write_set);
+            FD_ZERO (&except_set);
+          }
+      }
   }
 
   return scm_list_3 (retrieve_select_type (&read_set, read_ports_ready, reads),

This bug report was last modified 7 years and 96 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.