9
9
#include "pycore_sysmodule.h" // _PySys_GetRequiredAttr()
10
10
#include "pycore_time.h" // _PyTime_FromSecondsObject()
11
11
#include "pycore_traceback.h" // _Py_DumpTracebackThreads
12
-
13
12
#ifdef HAVE_UNISTD_H
14
13
# include <unistd.h> // _exit()
15
14
#endif
15
+
16
16
#include <signal.h> // sigaction()
17
17
#include <stdlib.h> // abort()
18
18
#if defined(HAVE_PTHREAD_SIGMASK ) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK ) && defined(HAVE_PTHREAD_H )
@@ -210,6 +210,25 @@ faulthandler_dump_traceback(int fd, int all_threads,
210
210
reentrant = 0 ;
211
211
}
212
212
213
+ static void
214
+ faulthandler_dump_c_stack (int fd )
215
+ {
216
+ static volatile int reentrant = 0 ;
217
+
218
+ if (reentrant ) {
219
+ return ;
220
+ }
221
+
222
+ reentrant = 1 ;
223
+
224
+ if (fatal_error .c_stack ) {
225
+ PUTS (fd , "\n" );
226
+ _Py_DumpStack (fd );
227
+ }
228
+
229
+ reentrant = 0 ;
230
+ }
231
+
213
232
static PyObject *
214
233
faulthandler_dump_traceback_py (PyObject * self ,
215
234
PyObject * args , PyObject * kwargs )
@@ -260,6 +279,33 @@ faulthandler_dump_traceback_py(PyObject *self,
260
279
Py_RETURN_NONE ;
261
280
}
262
281
282
+ static PyObject *
283
+ faulthandler_dump_c_stack_py (PyObject * self ,
284
+ PyObject * args , PyObject * kwargs )
285
+ {
286
+ static char * kwlist [] = {"file" , NULL };
287
+ PyObject * file = NULL ;
288
+
289
+ if (!PyArg_ParseTupleAndKeywords (args , kwargs ,
290
+ "|O:dump_c_stack" , kwlist ,
291
+ & file )) {
292
+ return NULL ;
293
+ }
294
+
295
+ int fd = faulthandler_get_fileno (& file );
296
+ if (fd < 0 ) {
297
+ return NULL ;
298
+ }
299
+
300
+ _Py_DumpStack (fd );
301
+
302
+ if (PyErr_CheckSignals ()) {
303
+ return NULL ;
304
+ }
305
+
306
+ Py_RETURN_NONE ;
307
+ }
308
+
263
309
static void
264
310
faulthandler_disable_fatal_handler (fault_handler_t * handler )
265
311
{
@@ -350,6 +396,7 @@ faulthandler_fatal_error(int signum)
350
396
351
397
faulthandler_dump_traceback (fd , deduce_all_threads (),
352
398
fatal_error .interp );
399
+ faulthandler_dump_c_stack (fd );
353
400
354
401
_Py_DumpExtensionModules (fd , fatal_error .interp );
355
402
@@ -425,6 +472,7 @@ faulthandler_exc_handler(struct _EXCEPTION_POINTERS *exc_info)
425
472
426
473
faulthandler_dump_traceback (fd , deduce_all_threads (),
427
474
fatal_error .interp );
475
+ faulthandler_dump_c_stack (fd );
428
476
429
477
/* call the next exception handler */
430
478
return EXCEPTION_CONTINUE_SEARCH ;
@@ -519,14 +567,15 @@ faulthandler_enable(void)
519
567
static PyObject *
520
568
faulthandler_py_enable (PyObject * self , PyObject * args , PyObject * kwargs )
521
569
{
522
- static char * kwlist [] = {"file" , "all_threads" , NULL };
570
+ static char * kwlist [] = {"file" , "all_threads" , "c_stack" , NULL };
523
571
PyObject * file = NULL ;
524
572
int all_threads = 1 ;
525
573
int fd ;
574
+ int c_stack = 1 ;
526
575
PyThreadState * tstate ;
527
576
528
577
if (!PyArg_ParseTupleAndKeywords (args , kwargs ,
529
- "|Op :enable" , kwlist , & file , & all_threads ))
578
+ "|Opp :enable" , kwlist , & file , & all_threads , & c_stack ))
530
579
return NULL ;
531
580
532
581
fd = faulthandler_get_fileno (& file );
@@ -543,6 +592,7 @@ faulthandler_py_enable(PyObject *self, PyObject *args, PyObject *kwargs)
543
592
fatal_error .fd = fd ;
544
593
fatal_error .all_threads = all_threads ;
545
594
fatal_error .interp = PyThreadState_GetInterpreter (tstate );
595
+ fatal_error .c_stack = c_stack ;
546
596
547
597
if (faulthandler_enable () < 0 ) {
548
598
return NULL ;
@@ -1238,6 +1288,10 @@ static PyMethodDef module_methods[] = {
1238
1288
PyDoc_STR ("dump_traceback($module, /, file=sys.stderr, all_threads=True)\n--\n\n"
1239
1289
"Dump the traceback of the current thread, or of all threads "
1240
1290
"if all_threads is True, into file." )},
1291
+ {"dump_c_stack" ,
1292
+ _PyCFunction_CAST (faulthandler_dump_c_stack_py ), METH_VARARGS |METH_KEYWORDS ,
1293
+ PyDoc_STR ("dump_c_stack($module, /, file=sys.stderr)\n--\n\n"
1294
+ "Dump the C stack of the current thread." )},
1241
1295
{"dump_traceback_later" ,
1242
1296
_PyCFunction_CAST (faulthandler_dump_traceback_later ), METH_VARARGS |METH_KEYWORDS ,
1243
1297
PyDoc_STR ("dump_traceback_later($module, /, timeout, repeat=False, file=sys.stderr, exit=False)\n--\n\n"
0 commit comments