[pypy-commit] pypy default: Like CPython 3, write a message to stderr if we can't write to wakeup_fd.

arigo pypy.commits at gmail.com
Wed Feb 1 10:54:04 EST 2017


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r89890:f38fce96ddce
Date: 2017-02-01 16:49 +0100
http://bitbucket.org/pypy/pypy/changeset/f38fce96ddce/

Log:	Like CPython 3, write a message to stderr if we can't write to
	wakeup_fd. Unlike CPython, the message is sent to fileno 2, not back
	through sys.stderr.

diff --git a/rpython/rlib/test/test_rsignal.py b/rpython/rlib/test/test_rsignal.py
--- a/rpython/rlib/test/test_rsignal.py
+++ b/rpython/rlib/test/test_rsignal.py
@@ -1,4 +1,4 @@
-import os, py
+import os, py, errno
 from rpython.translator.c.test.test_genc import compile
 from rpython.rlib import rsignal
 
@@ -37,3 +37,24 @@
 def test_compile():
     fn = compile(test_simple, [])
     fn()
+
+def test_compile_wakeup_fd():
+    def fn():
+        rd, wr = os.pipe()
+        rsignal.pypysig_set_wakeup_fd(wr, False)
+        for i in range(3):
+            rsignal.pypysig_setflag(rsignal.SIGUSR1)
+            os.kill(os.getpid(), rsignal.SIGUSR1)
+            check(rsignal.SIGUSR1)
+            check(-1)
+            check(-1)
+        x = os.read(rd, 10)
+        assert x == chr(rsignal.SIGUSR1) * 3
+        #
+        rsignal.pypysig_set_wakeup_fd(rd, False)   # can't write there
+        os.kill(os.getpid(), rsignal.SIGUSR1)
+
+    fn = compile(fn, [], return_stderr=True)
+    stderr = fn()
+    assert stderr.endswith('Exception ignored when trying to write to the '
+                           'signal wakeup fd: Errno %d\n' % errno.EBADF)
diff --git a/rpython/translator/c/src/signals.c b/rpython/translator/c/src/signals.c
--- a/rpython/translator/c/src/signals.c
+++ b/rpython/translator/c/src/signals.c
@@ -2,6 +2,7 @@
 
 #include <limits.h>
 #include <stdlib.h>
+#include <errno.h>
 #ifdef _WIN32
 #include <process.h>
 #include <io.h>
@@ -82,27 +83,51 @@
       }
 }
 
+static void write_str(int fd, const char *p)
+{
+    int i = 0;
+    while (p[i] != '\x00')
+        i++;
+    (void)write(fd, p, i);
+}
+
 static void signal_setflag_handler(int signum)
 {
     pypysig_pushback(signum);
 
-    if (wakeup_fd != -1) 
-      {
+    /* Warning, this logic needs to be async-signal-safe */
+    if (wakeup_fd != -1) {
 #ifndef _WIN32
         ssize_t res;
 #else
         int res;
 #endif
-	if (wakeup_with_nul_byte)
-	{
-	    res = write(wakeup_fd, "\0", 1);
-	} else {
-	    unsigned char byte = (unsigned char)signum;
-	    res = write(wakeup_fd, &byte, 1);
-	}
-
-        /* the return value is ignored here */
-      }
+        int old_errno = errno;
+     retry:
+        if (wakeup_with_nul_byte) {
+            res = write(wakeup_fd, "\0", 1);
+        } else {
+            unsigned char byte = (unsigned char)signum;
+            res = write(wakeup_fd, &byte, 1);
+        }
+        if (res < 0) {
+            unsigned int e = (unsigned int)errno;
+            char c[27], *p;
+            if (e == EINTR)
+                goto retry;
+            write_str(2, "Exception ignored when trying to write to the "
+                         "signal wakeup fd: Errno ");
+            p = c + sizeof(c);
+            *--p = 0;
+            *--p = '\n';
+            do {
+                *--p = '0' + e % 10;
+                e /= 10;
+            } while (e != 0);
+            write_str(2, p);
+        }
+        errno = old_errno;
+    }
 }
 
 void pypysig_setflag(int signum)


More information about the pypy-commit mailing list