Index: Python/pythonrun.c =================================================================== --- Python/pythonrun.c (révision 81613) +++ Python/pythonrun.c (copie de travail) @@ -80,6 +80,9 @@ extern void _PyGILState_Fini(void); #endif /* WITH_THREAD */ +extern void _Py_initsegfault(void); +extern void _Py_deinitsegfault(void); + int Py_DebugFlag; /* Needed by parser.c */ int Py_VerboseFlag; /* Needed by import.c */ int Py_InteractiveFlag; /* Needed by Py_FdIsInteractive() below */ @@ -377,6 +380,7 @@ interp = tstate->interp; /* Disable signal handling */ + _Py_deinitsegfault(); PyOS_FiniInterrupts(); /* Clear type lookup cache */ @@ -2174,6 +2178,7 @@ PyOS_setsig(SIGXFSZ, SIG_IGN); #endif PyOS_InitInterrupts(); /* May imply initsignal() */ + _Py_initsegfault(); } Index: Python/segfault.c =================================================================== --- Python/segfault.c (révision 0) +++ Python/segfault.c (révision 0) @@ -0,0 +1,102 @@ +#include "Python.h" +#include "frameobject.h" +#include "code.h" +#include +#include +#include + +static stack_t stack; +static int enable = 0; +static struct sigaction old_action; + +static void +dump_frame(struct _frame *f, int depth) +{ + PyCodeObject *code; + PyObject *filenameobj; + char *filename; + + code = f->f_code; + if (code != NULL) { + filenameobj = code->co_filename; + if (filenameobj != NULL && !PyUnicode_Check(filenameobj)) + filenameobj = NULL; + } else + filenameobj = NULL; + if (filenameobj != NULL) + filename = _PyUnicode_AsString(filenameobj); + else + filename = NULL; + if (filename != NULL && filename[0] != '\0') { + fputs(" File \"", stderr); + fputs(filename, stderr); + fputs("\"", stderr); + } else + fputs(" File ", stderr); + if (filenameobj != NULL) { + PyUnicodeObject *unicode = (PyUnicodeObject *)filenameobj; + Py_XDECREF(unicode->defenc); + unicode->defenc = NULL; + } + + fprintf(stderr, ", line %u, depth %i\n", f->f_lineno, depth); + fflush(stderr); +} + +static void +segfault(int signum) +{ + PyThreadState *tstate; + struct _frame *frame; + int depth; + + fputs("Fatal Python error: segmentation fault\n\n", stderr); + fflush(stderr); + tstate = ((PyThreadState*)_Py_atomic_load_relaxed(&_PyThreadState_Current)); + if (tstate == NULL) + goto exit; + + fputs("Traceback (most recent call first):\n", stderr); + depth = tstate->recursion_depth; + frame = tstate->frame; + while (frame != NULL) { + dump_frame(frame, depth); + frame = frame->f_back; + depth--; + } + fputs("Segmentation fault\n", stderr); + fflush(stderr); + +exit: + _exit(1); +} + +void _Py_initsegfault(void) +{ + struct sigaction action; + + stack.ss_size = SIGSTKSZ; + stack.ss_sp = PyMem_Malloc(stack.ss_size); + stack.ss_flags = SS_ONSTACK; + if (stack.ss_sp == NULL) + return; + if (sigaltstack(&stack, NULL) != 0) + return; + + /* FIXME: #ifdef HAVE_SIGACTION */ + action.sa_handler = segfault; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_ONSTACK; + if (sigaction(SIGSEGV, &action, &old_action) == 0) + enable = 1; +} + +void _Py_deinitsegfault(void) +{ + if (stack.ss_sp != NULL) + PyMem_Free(stack.ss_sp); + + if (enable) + (void)sigaction(SIGSEGV, &old_action, NULL); +} +