Commits

Amaury Forgeot d'Arc committed 898f225

Add the functions that crash the interpreter with various signals :-/

  • Participants
  • Parent commits e7c8a2c
  • Branches py3.3

Comments (0)

Files changed (3)

File pypy/module/faulthandler/__init__.py

         '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',
     }

File pypy/module/faulthandler/faulthandler.c

+#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

File pypy/module/faulthandler/interp_faulthandler.py

 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):
 
         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()