[pypy-commit] pypy default: Don't use sprintf() from inside a signal handler

arigo pypy.commits at gmail.com
Wed Oct 5 12:02:16 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r87596:6b566100b56f
Date: 2016-10-05 18:01 +0200
http://bitbucket.org/pypy/pypy/changeset/6b566100b56f/

Log:	Don't use sprintf() from inside a signal handler

diff --git a/pypy/module/faulthandler/cintf.py b/pypy/module/faulthandler/cintf.py
--- a/pypy/module/faulthandler/cintf.py
+++ b/pypy/module/faulthandler/cintf.py
@@ -42,8 +42,9 @@
 pypy_faulthandler_write = direct_llexternal(
     'pypy_faulthandler_write', [rffi.INT, rffi.CCHARP], lltype.Void)
 
-pypy_faulthandler_write_int = direct_llexternal(
-    'pypy_faulthandler_write_int', [rffi.INT, lltype.Signed], lltype.Void)
+pypy_faulthandler_write_uint = direct_llexternal(
+    'pypy_faulthandler_write_uint', [rffi.INT, lltype.Unsigned, rffi.INT],
+                                    lltype.Void)
 
 pypy_faulthandler_dump_traceback = direct_llexternal(
     'pypy_faulthandler_dump_traceback',
diff --git a/pypy/module/faulthandler/dumper.py b/pypy/module/faulthandler/dumper.py
--- a/pypy/module/faulthandler/dumper.py
+++ b/pypy/module/faulthandler/dumper.py
@@ -4,7 +4,7 @@
 
 from pypy.interpreter.pycode import PyCode
 from pypy.module.faulthandler.cintf import pypy_faulthandler_write
-from pypy.module.faulthandler.cintf import pypy_faulthandler_write_int
+from pypy.module.faulthandler.cintf import pypy_faulthandler_write_uint
 
 
 MAX_STRING_LENGTH = 500
@@ -24,8 +24,9 @@
     global_buf[l] = '\x00'
     pypy_faulthandler_write(fd, global_buf)
 
-def _dump_int(fd, i):
-    pypy_faulthandler_write_int(fd, i)
+def _dump_nonneg_int(fd, i):
+    pypy_faulthandler_write_uint(fd, rffi.cast(lltype.Unsigned, i),
+                                 rffi.cast(rffi.INT, 1))
 
 
 def dump_code(pycode, loc, fd):
@@ -37,7 +38,7 @@
         _dump(fd, '" in ')
         _dump(fd, pycode.co_name)
         _dump(fd, ", from line ")
-        _dump_int(fd, pycode.co_firstlineno)
+        _dump_nonneg_int(fd, pycode.co_firstlineno)
     if loc == traceback.LOC_JITTED:
         _dump(fd, " [jitted]")
     elif loc == traceback.LOC_JITTED_INLINED:
diff --git a/pypy/module/faulthandler/faulthandler.c b/pypy/module/faulthandler/faulthandler.c
--- a/pypy/module/faulthandler/faulthandler.c
+++ b/pypy/module/faulthandler/faulthandler.c
@@ -60,15 +60,53 @@
 RPY_EXTERN
 void pypy_faulthandler_write(int fd, const char *str)
 {
-    (void)write(fd, str, strlen(str));
+    ssize_t n, count;
+    count = 0;
+    while (str[count] != 0)
+        count++;
+
+    while (count > 0) {
+        n = write(fd, str, count);
+        if (n < 0) {
+            if (errno != EINTR)
+                return;   /* give up */
+            n = 0;
+        }
+        str += n;
+        count -= n;
+    }
 }
 
 RPY_EXTERN
-void pypy_faulthandler_write_int(int fd, long value)
+void pypy_faulthandler_write_uint(int fd, unsigned long uvalue, int min_digits)
 {
-    char buf[48];
-    sprintf(buf, "%ld", value);
-    pypy_faulthandler_write(fd, buf);
+    char buf[48], *p = buf + 48;
+    *--p = 0;
+    while (uvalue || min_digits > 0) {
+        assert(p > buf);
+        *--p = '0' + (uvalue % 10UL);
+        uvalue /= 10UL;
+        min_digits--;
+    }
+
+    pypy_faulthandler_write(fd, p);
+}
+
+static void pypy_faulthandler_write_hex(int fd, unsigned long uvalue)
+{
+    char buf[48], *p = buf + 48;
+    *--p = 0;
+    do {
+        unsigned long byte = uvalue % 16UL;
+        assert(p > buf);
+        if (byte < 10)
+            *--p = '0' + byte;
+        else
+            *--p = 'A' + byte - 10;
+        uvalue /= 16UL;
+    } while (uvalue > 0UL);
+
+    pypy_faulthandler_write(fd, p);
 }
 
 
@@ -91,7 +129,6 @@
         */
         struct pypy_threadlocal_s *my, *p;
         int blankline = 0;
-        char buf[40];
 
         my = (struct pypy_threadlocal_s *)_RPy_ThreadLocals_Get();
         p = _RPython_ThreadLocals_Head();
@@ -101,9 +138,9 @@
                 pypy_faulthandler_write(fd, "\n");
             blankline = 1;
 
-            pypy_faulthandler_write(fd, my == p ? "Current thread" : "Thread");
-            sprintf(buf, " 0x%lx", (unsigned long)p->thread_ident);
-            pypy_faulthandler_write(fd, buf);
+            pypy_faulthandler_write(fd, my == p ? "Current thread 0x"
+                                                : "Thread 0x");
+            pypy_faulthandler_write_hex(fd, (unsigned long)p->thread_ident);
             pypy_faulthandler_write(fd, " (most recent call first):\n");
 
             array_length = vmprof_get_traceback(p->vmprof_tl_stack,
@@ -166,9 +203,9 @@
 #endif
 
     RPyLockStatus st;
-    char buf[64];
-    unsigned long hour, minutes, seconds, fraction;
+    unsigned long hours, minutes, seconds, fraction;
     long long t;
+    int fd;
 
     do {
         st = RPyThreadAcquireLockTimed(&thread_later.cancel_event,
@@ -190,16 +227,21 @@
         t /= 60;
         minutes = (unsigned long)(t % 60);
         t /= 60;
-        hour = (unsigned long)t;
-        if (fraction == 0)
-            sprintf(buf, "Timeout (%lu:%02lu:%02lu)!\n",
-                    hour, minutes, seconds);
-        else
-            sprintf(buf, "Timeout (%lu:%02lu:%02lu.%06lu)!\n",
-                    hour, minutes, seconds, fraction);
+        hours = (unsigned long)t;
 
-        pypy_faulthandler_write(thread_later.fd, buf);
-        pypy_faulthandler_dump_traceback(thread_later.fd, 1, NULL);
+        fd = thread_later.fd;
+        pypy_faulthandler_write(fd, "Timeout (");
+        pypy_faulthandler_write_uint(fd, hours, 1);
+        pypy_faulthandler_write(fd, ":");
+        pypy_faulthandler_write_uint(fd, minutes, 2);
+        pypy_faulthandler_write(fd, ":");
+        pypy_faulthandler_write_uint(fd, seconds, 2);
+        if (fraction != 0) {
+            pypy_faulthandler_write(fd, ".");
+            pypy_faulthandler_write_uint(fd, fraction, 6);
+        }
+        pypy_faulthandler_write(fd, ")!\n");
+        pypy_faulthandler_dump_traceback(fd, 1, NULL);
 
         if (thread_later.exit)
             _exit(1);
diff --git a/pypy/module/faulthandler/faulthandler.h b/pypy/module/faulthandler/faulthandler.h
--- a/pypy/module/faulthandler/faulthandler.h
+++ b/pypy/module/faulthandler/faulthandler.h
@@ -16,7 +16,8 @@
 RPY_EXTERN int pypy_faulthandler_is_enabled(void);
 
 RPY_EXTERN void pypy_faulthandler_write(int fd, const char *str);
-RPY_EXTERN void pypy_faulthandler_write_int(int fd, long value);
+RPY_EXTERN void pypy_faulthandler_write_uint(int fd, unsigned long value,
+                                             int min_digits);
 
 RPY_EXTERN void pypy_faulthandler_dump_traceback(int fd, int all_threads,
                                                  void *ucontext);


More information about the pypy-commit mailing list