55#include <frameobject.h>
66#include <signal.h>
77
8+ /* Allocate at maximum 100 MB of the stack to raise the stack overflow */
9+ #define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
10+
811#ifdef WITH_THREAD
912# define FAULTHANDLER_LATER
1013#endif
1619# define FAULTHANDLER_USER
1720#endif
1821
19- /* Allocate at maximum 100 MB of the stack to raise the stack overflow */
20- #define STACK_OVERFLOW_MAX_SIZE (100*1024*1024)
21-
2222#define PUTS (fd , str ) write(fd, str, strlen(str))
2323
2424#ifdef HAVE_SIGACTION
@@ -451,8 +451,8 @@ faulthandler_cancel_dump_tracebacks_later(void)
451451}
452452
453453static PyObject *
454- faulthandler_dump_traceback_later (PyObject * self ,
455- PyObject * args , PyObject * kwargs )
454+ faulthandler_dump_tracebacks_later (PyObject * self ,
455+ PyObject * args , PyObject * kwargs )
456456{
457457 static char * kwlist [] = {"timeout" , "repeat" , "file" , "exit" , NULL };
458458 double timeout ;
@@ -461,6 +461,7 @@ faulthandler_dump_traceback_later(PyObject *self,
461461 PyObject * file = NULL ;
462462 int fd ;
463463 int exit = 0 ;
464+ PyThreadState * tstate ;
464465
465466 if (!PyArg_ParseTupleAndKeywords (args , kwargs ,
466467 "d|iOi:dump_tracebacks_later" , kwlist ,
@@ -477,6 +478,13 @@ faulthandler_dump_traceback_later(PyObject *self,
477478 return NULL ;
478479 }
479480
481+ tstate = PyThreadState_Get ();
482+ if (tstate == NULL ) {
483+ PyErr_SetString (PyExc_RuntimeError ,
484+ "unable to get the current thread state" );
485+ return NULL ;
486+ }
487+
480488 file = faulthandler_get_fileno (file , & fd );
481489 if (file == NULL )
482490 return NULL ;
@@ -490,7 +498,7 @@ faulthandler_dump_traceback_later(PyObject *self,
490498 thread .fd = fd ;
491499 thread .timeout_ms = timeout_ms ;
492500 thread .repeat = repeat ;
493- thread .interp = PyThreadState_Get () -> interp ;
501+ thread .interp = tstate -> interp ;
494502 thread .exit = exit ;
495503
496504 /* Arm these locks to serve as events when released */
@@ -826,16 +834,16 @@ static int
826834faulthandler_traverse (PyObject * module , visitproc visit , void * arg )
827835{
828836#ifdef FAULTHANDLER_USER
829- unsigned int index ;
837+ unsigned int signum ;
830838#endif
831839
832840#ifdef FAULTHANDLER_LATER
833841 Py_VISIT (thread .file );
834842#endif
835843#ifdef FAULTHANDLER_USER
836844 if (user_signals != NULL ) {
837- for (index = 0 ; index < NSIG ; index ++ )
838- Py_VISIT (user_signals [index ].file );
845+ for (signum = 0 ; signum < NSIG ; signum ++ )
846+ Py_VISIT (user_signals [signum ].file );
839847 }
840848#endif
841849 Py_VISIT (fatal_error .file );
@@ -861,10 +869,11 @@ static PyMethodDef module_methods[] = {
861869 "if all_threads is True, into file" )},
862870#ifdef FAULTHANDLER_LATER
863871 {"dump_tracebacks_later" ,
864- (PyCFunction )faulthandler_dump_traceback_later , METH_VARARGS |METH_KEYWORDS ,
865- PyDoc_STR ("dump_tracebacks_later(timeout, repeat=False, file=sys.stderr ):\n"
872+ (PyCFunction )faulthandler_dump_tracebacks_later , METH_VARARGS |METH_KEYWORDS ,
873+ PyDoc_STR ("dump_tracebacks_later(timeout, repeat=False, file=sys.stderrn, exit=False ):\n"
866874 "dump the traceback of all threads in timeout seconds,\n"
867- "or each timeout seconds if repeat is True." )},
875+ "or each timeout seconds if repeat is True. If exit is True, "
876+ "call _exit(1) which is not safe." )},
868877 {"cancel_dump_tracebacks_later" ,
869878 (PyCFunction )faulthandler_cancel_dump_tracebacks_later_py , METH_NOARGS ,
870879 PyDoc_STR ("cancel_dump_tracebacks_later():\ncancel the previous call "
0 commit comments