[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