Author: Amaury Forgeot d'Arc <[email protected]>
Branch: py3.3
Changeset: r73046:898f225422d2
Date: 2014-08-17 23:48 +0200
http://bitbucket.org/pypy/pypy/changeset/898f225422d2/
Log: Add the functions that crash the interpreter with various signals
:-/
diff --git a/pypy/module/faulthandler/__init__.py
b/pypy/module/faulthandler/__init__.py
--- a/pypy/module/faulthandler/__init__.py
+++ b/pypy/module/faulthandler/__init__.py
@@ -11,4 +11,11 @@
'register': 'interp_faulthandler.register',
'dump_traceback': 'interp_faulthandler.dump_traceback',
+
+ '_read_null': 'interp_faulthandler.read_null',
+ '_sigsegv': 'interp_faulthandler.sigsegv',
+ '_sigfpe': 'interp_faulthandler.sigfpe',
+ '_sigabrt': 'interp_faulthandler.sigabrt',
+ '_sigbus': 'interp_faulthandler.sigbus',
+ '_sigill': 'interp_faulthandler.sigill',
}
diff --git a/pypy/module/faulthandler/faulthandler.c
b/pypy/module/faulthandler/faulthandler.c
new file mode 100644
--- /dev/null
+++ b/pypy/module/faulthandler/faulthandler.c
@@ -0,0 +1,77 @@
+#include <signal.h>
+#include <stdlib.h>
+
+int
+pypy_faulthandler_read_null(void)
+{
+ volatile int *x;
+ volatile int y;
+
+ x = NULL;
+ y = *x;
+ return y;
+}
+
+void
+pypy_faulthandler_sigsegv(void)
+{
+#if defined(MS_WINDOWS)
+ /* For SIGSEGV, faulthandler_fatal_error() restores the previous signal
+ handler and then gives back the execution flow to the program (without
+ explicitly calling the previous error handler). In a normal case, the
+ SIGSEGV was raised by the kernel because of a fault, and so if the
+ program retries to execute the same instruction, the fault will be
+ raised again.
+
+ Here the fault is simulated by a fake SIGSEGV signal raised by the
+ application. We have to raise SIGSEGV at lease twice: once for
+ faulthandler_fatal_error(), and one more time for the previous signal
+ handler. */
+ while(1)
+ raise(SIGSEGV);
+#else
+ raise(SIGSEGV);
+#endif
+}
+
+int
+pypy_faulthandler_sigfpe(void)
+{
+ /* Do an integer division by zero: raise a SIGFPE on Intel CPU, but not on
+ PowerPC. Use volatile to disable compile-time optimizations. */
+ volatile int x = 1, y = 0, z;
+ z = x / y;
+ /* If the division by zero didn't raise a SIGFPE (e.g. on PowerPC),
+ raise it manually. */
+ raise(SIGFPE);
+ /* This line is never reached, but we pretend to make something with z
+ to silence a compiler warning. */
+ return z;
+}
+
+void
+pypy_faulthandler_sigabrt()
+{
+#ifdef _MSC_VER
+ /* Visual Studio: configure abort() to not display an error message nor
+ open a popup asking to report the fault. */
+ _set_abort_behavior(0, _WRITE_ABORT_MSG | _CALL_REPORTFAULT);
+#endif
+ abort();
+}
+
+#ifdef SIGBUS
+void
+pypy_faulthandler_sigbus(void)
+{
+ raise(SIGBUS);
+}
+#endif
+
+#ifdef SIGILL
+void
+pypy_faulthandler_sigill(void)
+{
+ raise(SIGILL);
+}
+#endif
diff --git a/pypy/module/faulthandler/interp_faulthandler.py
b/pypy/module/faulthandler/interp_faulthandler.py
--- a/pypy/module/faulthandler/interp_faulthandler.py
+++ b/pypy/module/faulthandler/interp_faulthandler.py
@@ -1,7 +1,44 @@
import os
+import py
from pypy.interpreter.gateway import interp2app, unwrap_spec, WrappedDefault
+from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.interpreter.error import OperationError, oefmt
+cwd = py.path.local(__file__).dirpath()
+eci = ExternalCompilationInfo(
+ includes=[cwd.join('faulthandler.h')],
+ include_dirs=[str(cwd)],
+ separate_module_files=[cwd.join('faulthandler.c')],
+ export_symbols=['pypy_faulthandler_read_null',
+ 'pypy_faulthandler_sigsegv',
+ 'pypy_faulthandler_sigfpe',
+ 'pypy_faulthandler_sigabrt',
+ 'pypy_faulthandler_sigbus',
+ 'pypy_faulthandler_sigill',
+ ])
+
+def llexternal(*args, **kwargs):
+ kwargs.setdefault('releasegil', False)
+ kwargs.setdefault('compilation_info', eci)
+ return rffi.llexternal(*args, **kwargs)
+
+pypy_faulthandler_read_null = llexternal(
+ 'pypy_faulthandler_read_null', [], lltype.Void)
+pypy_faulthandler_read_null_nogil = llexternal(
+ 'pypy_faulthandler_read_null', [], lltype.Void,
+ releasegil=True)
+pypy_faulthandler_sigsegv = llexternal(
+ 'pypy_faulthandler_sigsegv', [], lltype.Void)
+pypy_faulthandler_sigfpe = llexternal(
+ 'pypy_faulthandler_sigfpe', [], lltype.Void)
+pypy_faulthandler_sigabrt = llexternal(
+ 'pypy_faulthandler_sigabrt', [], lltype.Void)
+pypy_faulthandler_sigbus = llexternal(
+ 'pypy_faulthandler_sigbus', [], lltype.Void)
+pypy_faulthandler_sigill = llexternal(
+ 'pypy_faulthandler_sigill', [], lltype.Void)
class FatalErrorState(object):
def __init__(self, space):
@@ -43,3 +80,25 @@
frame = frame.f_backref()
+
+@unwrap_spec(w_release_gil=WrappedDefault(False))
+def read_null(space, w_release_gil):
+ if space.is_true(w_release_gil):
+ pypy_faulthandler_read_null_nogil()
+ else:
+ pypy_faulthandler_read_null()
+
+def sigsegv():
+ pypy_faulthandler_sigsegv()
+
+def sigfpe():
+ pypy_faulthandler_sigfpe()
+
+def sigabrt():
+ pypy_faulthandler_sigabrt()
+
+def sigbus():
+ pypy_faulthandler_sigbus()
+
+def sigill():
+ pypy_faulthandler_sigill()
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit