Coverage Report

Created: 2026-08-31 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cpython3/Python/traceback.c
Line
Count
Source
1
2
/* Traceback implementation */
3
4
#include "Python.h"
5
#include "pycore_call.h"          // _PyObject_CallMethodFormat()
6
#include "pycore_fileutils.h"     // _Py_BEGIN_SUPPRESS_IPH
7
#include "pycore_frame.h"         // PyFrameObject
8
#include "pycore_interp.h"        // PyInterpreterState.gc
9
#include "pycore_interpframe.h"   // _PyFrame_GetCode()
10
#include "pycore_pyerrors.h"      // _PyErr_GetRaisedException()
11
#include "pycore_pystate.h"       // _PyThreadState_GET()
12
#include "pycore_traceback.h"     // EXCEPTION_TB_HEADER
13
14
#include "frameobject.h"          // PyFrame_New()
15
#include "../Parser/tokenizer/tokenizer.h"
16
17
#include "osdefs.h"               // SEP
18
#ifdef HAVE_UNISTD_H
19
#  include <unistd.h>             // lseek()
20
#endif
21
22
#if (defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H) && defined(HAVE_LINK_H))
23
#  define _PY_HAS_BACKTRACE_HEADERS 1
24
#endif
25
26
#if (defined(__APPLE__) && defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H))
27
#  define _PY_HAS_BACKTRACE_HEADERS 1
28
#endif
29
30
#ifdef _PY_HAS_BACKTRACE_HEADERS
31
#  include <execinfo.h>           // backtrace(), backtrace_symbols()
32
#  include <dlfcn.h>              // dladdr1()
33
#ifdef HAVE_LINK_H
34
#    include <link.h>               // struct DL_info
35
#endif
36
#  if defined(__APPLE__) && defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR)
37
#    define CAN_C_BACKTRACE
38
#  elif defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR1)
39
#    define CAN_C_BACKTRACE
40
#  endif
41
#endif
42
43
#if defined(__STDC_NO_VLA__) && (__STDC_NO_VLA__ == 1)
44
/* Use alloca() for VLAs. */
45
#  define VLA(type, name, size) type *name = alloca(sizeof(type) * (size))
46
#elif !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ == 0)
47
/* Use actual C VLAs.*/
48
0
#  define VLA(type, name, size) type name[size]
49
#elif defined(CAN_C_BACKTRACE)
50
/* VLAs are not possible. Disable C stack trace functions. */
51
#  undef CAN_C_BACKTRACE
52
#endif
53
54
#define OFF(x) offsetof(PyTracebackObject, x)
55
0
#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str))
56
57
0
#define MAX_STRING_LENGTH 500
58
0
#define MAX_FRAME_DEPTH 100
59
0
#define DEFAULT_MAX_NTHREADS 100
60
61
/*[clinic input]
62
class traceback "PyTracebackObject *" "&PyTraceback_Type"
63
[clinic start generated code]*/
64
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/
65
66
3.42M
#define _PyTracebackObject_CAST(op)   ((PyTracebackObject *)(op))
67
68
#include "clinic/traceback.c.h"
69
70
71
#ifdef MS_WINDOWS
72
typedef HRESULT (WINAPI *PF_GET_THREAD_DESCRIPTION)(HANDLE, PWSTR*);
73
static PF_GET_THREAD_DESCRIPTION pGetThreadDescription = NULL;
74
#endif
75
76
77
static PyObject *
78
tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,
79
              int lineno)
80
3.42M
{
81
3.42M
    PyTracebackObject *tb;
82
3.42M
    if ((next != NULL && !PyTraceBack_Check(next)) ||
83
3.42M
                    frame == NULL || !PyFrame_Check(frame)) {
84
0
        PyErr_BadInternalCall();
85
0
        return NULL;
86
0
    }
87
3.42M
    tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
88
3.42M
    if (tb != NULL) {
89
3.42M
        tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);
90
3.42M
        tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);
91
3.42M
        tb->tb_lasti = lasti;
92
3.42M
        tb->tb_lineno = lineno;
93
3.42M
        PyObject_GC_Track(tb);
94
3.42M
    }
95
3.42M
    return (PyObject *)tb;
96
3.42M
}
97
98
/*[clinic input]
99
@classmethod
100
traceback.__new__ as tb_new
101
102
  tb_next: object
103
  tb_frame: object(type='PyFrameObject *', subclass_of='&PyFrame_Type')
104
  tb_lasti: int
105
  tb_lineno: int
106
107
Create a new traceback object.
108
[clinic start generated code]*/
109
110
static PyObject *
111
tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
112
            int tb_lasti, int tb_lineno)
113
/*[clinic end generated code: output=fa077debd72d861a input=b88143145454cb59]*/
114
0
{
115
0
    if (tb_next == Py_None) {
116
0
        tb_next = NULL;
117
0
    } else if (!PyTraceBack_Check(tb_next)) {
118
0
        return PyErr_Format(PyExc_TypeError,
119
0
                            "expected traceback object or None, got '%s'",
120
0
                            Py_TYPE(tb_next)->tp_name);
121
0
    }
122
123
0
    return tb_create_raw((PyTracebackObject *)tb_next, tb_frame, tb_lasti,
124
0
                         tb_lineno);
125
0
}
126
127
static PyObject *
128
tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
129
0
{
130
0
    return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
131
0
                                   "tb_lasti", "tb_lineno");
132
0
}
133
134
/*[clinic input]
135
@critical_section
136
@getter
137
traceback.tb_next
138
[clinic start generated code]*/
139
140
static PyObject *
141
traceback_tb_next_get_impl(PyTracebackObject *self)
142
/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
143
0
{
144
0
    PyObject* ret = (PyObject*)self->tb_next;
145
0
    if (!ret) {
146
0
        ret = Py_None;
147
0
    }
148
0
    return Py_NewRef(ret);
149
0
}
150
151
static int
152
tb_get_lineno(PyObject *op)
153
0
{
154
0
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
155
0
    _PyInterpreterFrame* frame = tb->tb_frame->f_frame;
156
0
    assert(frame != NULL);
157
0
    return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
158
0
}
159
160
static PyObject *
161
tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
162
0
{
163
0
    PyTracebackObject *self = _PyTracebackObject_CAST(op);
164
0
    int lineno = self->tb_lineno;
165
0
    if (lineno == -1) {
166
0
        lineno = tb_get_lineno(op);
167
0
        if (lineno < 0) {
168
0
            Py_RETURN_NONE;
169
0
        }
170
0
    }
171
0
    return PyLong_FromLong(lineno);
172
0
}
173
174
/*[clinic input]
175
@critical_section
176
@setter
177
@deleter
178
traceback.tb_next
179
[clinic start generated code]*/
180
181
static int
182
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value)
183
/*[clinic end generated code: output=d4868cbc48f2adac input=936201ff689c5700]*/
184
0
{
185
0
    if (!value) {
186
0
        PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
187
0
        return -1;
188
0
    }
189
190
    /* We accept None or a traceback object, and map None -> NULL (inverse of
191
       tb_next_get) */
192
0
    if (value == Py_None) {
193
0
        value = NULL;
194
0
    } else if (!PyTraceBack_Check(value)) {
195
0
        PyErr_Format(PyExc_TypeError,
196
0
                     "expected traceback object, got '%s'",
197
0
                     Py_TYPE(value)->tp_name);
198
0
        return -1;
199
0
    }
200
201
    /* Check for loops */
202
0
    PyTracebackObject *cursor = (PyTracebackObject *)value;
203
0
    Py_XINCREF(cursor);
204
0
    while (cursor) {
205
0
        if (cursor == self) {
206
0
            PyErr_Format(PyExc_ValueError, "traceback loop detected");
207
0
            Py_DECREF(cursor);
208
0
            return -1;
209
0
        }
210
0
        Py_BEGIN_CRITICAL_SECTION(cursor);
211
0
        Py_XINCREF(cursor->tb_next);
212
0
        Py_SETREF(cursor, cursor->tb_next);
213
0
        Py_END_CRITICAL_SECTION();
214
0
    }
215
216
0
    Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value));
217
218
0
    return 0;
219
0
}
220
221
222
static PyMethodDef tb_methods[] = {
223
   {"__dir__", tb_dir, METH_NOARGS, NULL},
224
   {NULL, NULL, 0, NULL},
225
};
226
227
static PyMemberDef tb_memberlist[] = {
228
    {"tb_frame",        _Py_T_OBJECT,       OFF(tb_frame),  Py_READONLY|Py_AUDIT_READ},
229
    {"tb_lasti",        Py_T_INT,          OFF(tb_lasti),  Py_READONLY},
230
    {NULL}      /* Sentinel */
231
};
232
233
static PyGetSetDef tb_getsetters[] = {
234
    TRACEBACK_TB_NEXT_GETSETDEF
235
    {"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
236
    {NULL}      /* Sentinel */
237
};
238
239
static void
240
tb_dealloc(PyObject *op)
241
3.42M
{
242
3.42M
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
243
3.42M
    PyObject_GC_UnTrack(tb);
244
3.42M
    Py_XDECREF(tb->tb_next);
245
3.42M
    Py_XDECREF(tb->tb_frame);
246
3.42M
    PyObject_GC_Del(tb);
247
3.42M
}
248
249
static int
250
tb_traverse(PyObject *op, visitproc visit, void *arg)
251
18
{
252
18
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
253
18
    Py_VISIT(tb->tb_next);
254
18
    Py_VISIT(tb->tb_frame);
255
18
    return 0;
256
18
}
257
258
static int
259
tb_clear(PyObject *op)
260
0
{
261
0
    PyTracebackObject *tb = _PyTracebackObject_CAST(op);
262
0
    Py_CLEAR(tb->tb_next);
263
0
    Py_CLEAR(tb->tb_frame);
264
0
    return 0;
265
0
}
266
267
PyTypeObject PyTraceBack_Type = {
268
    PyVarObject_HEAD_INIT(&PyType_Type, 0)
269
    "traceback",
270
    sizeof(PyTracebackObject),
271
    0,
272
    tb_dealloc,         /*tp_dealloc*/
273
    0,                  /*tp_vectorcall_offset*/
274
    0,    /*tp_getattr*/
275
    0,                  /*tp_setattr*/
276
    0,                  /*tp_as_async*/
277
    0,                  /*tp_repr*/
278
    0,                  /*tp_as_number*/
279
    0,                  /*tp_as_sequence*/
280
    0,                  /*tp_as_mapping*/
281
    0,                  /* tp_hash */
282
    0,                  /* tp_call */
283
    0,                  /* tp_str */
284
    PyObject_GenericGetAttr,                    /* tp_getattro */
285
    0,                  /* tp_setattro */
286
    0,                                          /* tp_as_buffer */
287
    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
288
    tb_new__doc__,                              /* tp_doc */
289
    tb_traverse,                                /* tp_traverse */
290
    tb_clear,                                   /* tp_clear */
291
    0,                                          /* tp_richcompare */
292
    0,                                          /* tp_weaklistoffset */
293
    0,                                          /* tp_iter */
294
    0,                                          /* tp_iternext */
295
    tb_methods,         /* tp_methods */
296
    tb_memberlist,      /* tp_members */
297
    tb_getsetters,                              /* tp_getset */
298
    0,                                          /* tp_base */
299
    0,                                          /* tp_dict */
300
    0,                                          /* tp_descr_get */
301
    0,                                          /* tp_descr_set */
302
    0,                                          /* tp_dictoffset */
303
    0,                                          /* tp_init */
304
    0,                                          /* tp_alloc */
305
    tb_new,                                     /* tp_new */
306
};
307
308
309
PyObject*
310
_PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
311
3.42M
{
312
3.42M
    assert(tb_next == NULL || PyTraceBack_Check(tb_next));
313
3.42M
    assert(frame != NULL);
314
3.42M
    int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
315
3.42M
    return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
316
3.42M
}
317
318
319
int
320
PyTraceBack_Here(PyFrameObject *frame)
321
3.42M
{
322
3.42M
    PyObject *exc = PyErr_GetRaisedException();
323
3.42M
    assert(PyExceptionInstance_Check(exc));
324
3.42M
    PyObject *tb = PyException_GetTraceback(exc);
325
3.42M
    PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);
326
3.42M
    Py_XDECREF(tb);
327
3.42M
    if (newtb == NULL) {
328
0
        _PyErr_ChainExceptions1(exc);
329
0
        return -1;
330
0
    }
331
3.42M
    PyException_SetTraceback(exc, newtb);
332
3.42M
    Py_XDECREF(newtb);
333
3.42M
    PyErr_SetRaisedException(exc);
334
3.42M
    return 0;
335
3.42M
}
336
337
/* Insert a frame into the traceback for (funcname, filename, lineno). */
338
void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
339
0
{
340
0
    PyObject *globals;
341
0
    PyCodeObject *code;
342
0
    PyFrameObject *frame;
343
0
    PyThreadState *tstate = _PyThreadState_GET();
344
345
    /* Save and clear the current exception. Python functions must not be
346
       called with an exception set. Calling Python functions happens when
347
       the codec of the filesystem encoding is implemented in pure Python. */
348
0
    PyObject *exc = _PyErr_GetRaisedException(tstate);
349
350
0
    globals = PyDict_New();
351
0
    if (!globals)
352
0
        goto error;
353
0
    code = PyCode_NewEmpty(filename, funcname, lineno);
354
0
    if (!code) {
355
0
        Py_DECREF(globals);
356
0
        goto error;
357
0
    }
358
0
    frame = PyFrame_New(tstate, code, globals, NULL);
359
0
    Py_DECREF(globals);
360
0
    Py_DECREF(code);
361
0
    if (!frame)
362
0
        goto error;
363
0
    frame->f_lineno = lineno;
364
365
0
    _PyErr_SetRaisedException(tstate, exc);
366
0
    PyTraceBack_Here(frame);
367
0
    Py_DECREF(frame);
368
0
    return;
369
370
0
error:
371
0
    _PyErr_ChainExceptions1(exc);
372
0
}
373
374
static PyObject *
375
_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
376
0
{
377
0
    Py_ssize_t i;
378
0
    PyObject *binary;
379
0
    PyObject *v;
380
0
    Py_ssize_t npath;
381
0
    size_t taillen;
382
0
    PyObject *syspath;
383
0
    PyObject *path;
384
0
    const char* tail;
385
0
    PyObject *filebytes;
386
0
    const char* filepath;
387
0
    Py_ssize_t len;
388
0
    PyObject* result;
389
0
    PyObject *open = NULL;
390
391
0
    filebytes = PyUnicode_EncodeFSDefault(filename);
392
0
    if (filebytes == NULL) {
393
0
        PyErr_Clear();
394
0
        return NULL;
395
0
    }
396
0
    filepath = PyBytes_AS_STRING(filebytes);
397
398
    /* Search tail of filename in sys.path before giving up */
399
0
    tail = strrchr(filepath, SEP);
400
0
    if (tail == NULL)
401
0
        tail = filepath;
402
0
    else
403
0
        tail++;
404
0
    taillen = strlen(tail);
405
406
0
    PyThreadState *tstate = _PyThreadState_GET();
407
0
    if (PySys_GetOptionalAttr(&_Py_ID(path), &syspath) < 0) {
408
0
        PyErr_Clear();
409
0
        goto error;
410
0
    }
411
0
    if (syspath == NULL || !PyList_Check(syspath)) {
412
0
        goto error;
413
0
    }
414
0
    npath = PyList_Size(syspath);
415
416
0
    open = PyObject_GetAttr(io, &_Py_ID(open));
417
0
    if (open == NULL) {
418
0
        goto error;
419
0
    }
420
0
    for (i = 0; i < npath; i++) {
421
0
        v = PyList_GetItem(syspath, i);
422
0
        if (v == NULL) {
423
0
            PyErr_Clear();
424
0
            break;
425
0
        }
426
0
        if (!PyUnicode_Check(v))
427
0
            continue;
428
0
        path = PyUnicode_EncodeFSDefault(v);
429
0
        if (path == NULL) {
430
0
            PyErr_Clear();
431
0
            continue;
432
0
        }
433
0
        len = PyBytes_GET_SIZE(path);
434
0
        if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
435
0
            Py_DECREF(path);
436
0
            continue; /* Too long */
437
0
        }
438
0
        strcpy(namebuf, PyBytes_AS_STRING(path));
439
0
        Py_DECREF(path);
440
0
        if (strlen(namebuf) != (size_t)len)
441
0
            continue; /* v contains '\0' */
442
0
        if (len > 0 && namebuf[len-1] != SEP)
443
0
            namebuf[len++] = SEP;
444
0
        strcpy(namebuf+len, tail);
445
446
0
        binary = _PyObject_CallMethodFormat(tstate, open, "ss", namebuf, "rb");
447
0
        if (binary != NULL) {
448
0
            result = binary;
449
0
            goto finally;
450
0
        }
451
0
        PyErr_Clear();
452
0
    }
453
0
    goto error;
454
455
0
error:
456
0
    result = NULL;
457
0
finally:
458
0
    Py_XDECREF(open);
459
0
    Py_XDECREF(syspath);
460
0
    Py_DECREF(filebytes);
461
0
    return result;
462
0
}
463
464
/* Writes indent spaces. Returns 0 on success and non-zero on failure.
465
 */
466
int
467
_Py_WriteIndent(int indent, PyObject *f)
468
0
{
469
0
    char buf[11] = "          ";
470
0
    assert(strlen(buf) == 10);
471
0
    while (indent > 0) {
472
0
        if (indent < 10) {
473
0
            buf[indent] = '\0';
474
0
        }
475
0
        if (PyFile_WriteString(buf, f) < 0) {
476
0
            return -1;
477
0
        }
478
0
        indent -= 10;
479
0
    }
480
0
    return 0;
481
0
}
482
483
static int
484
display_source_line(PyObject *f, PyObject *filename, int lineno, int indent,
485
                    int *truncation, PyObject **line)
486
0
{
487
0
    int fd;
488
0
    int i;
489
0
    char *found_encoding;
490
0
    const char *encoding;
491
0
    PyObject *io;
492
0
    PyObject *binary;
493
0
    PyObject *fob = NULL;
494
0
    PyObject *lineobj = NULL;
495
0
    PyObject *res;
496
0
    char buf[MAXPATHLEN+1];
497
0
    int kind;
498
0
    const void *data;
499
500
    /* open the file */
501
0
    if (filename == NULL)
502
0
        return 0;
503
504
    /* Do not attempt to open things like <string> or <stdin> */
505
0
    assert(PyUnicode_Check(filename));
506
0
    if (PyUnicode_READ_CHAR(filename, 0) == '<') {
507
0
        Py_ssize_t len = PyUnicode_GET_LENGTH(filename);
508
0
        if (len > 0 && PyUnicode_READ_CHAR(filename, len - 1) == '>') {
509
0
            return 0;
510
0
        }
511
0
    }
512
513
0
    io = PyImport_ImportModule("io");
514
0
    if (io == NULL) {
515
0
        return -1;
516
0
    }
517
518
0
    binary = _PyObject_CallMethod(io, &_Py_ID(open), "Os", filename, "rb");
519
0
    if (binary == NULL) {
520
0
        PyErr_Clear();
521
522
0
        binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
523
0
        if (binary == NULL) {
524
0
            Py_DECREF(io);
525
0
            return -1;
526
0
        }
527
0
    }
528
529
    /* use the right encoding to decode the file as unicode */
530
0
    fd = PyObject_AsFileDescriptor(binary);
531
0
    if (fd < 0) {
532
0
        Py_DECREF(io);
533
0
        Py_DECREF(binary);
534
0
        return 0;
535
0
    }
536
0
    found_encoding = _PyTokenizer_FindEncodingFilename(fd, filename);
537
0
    if (found_encoding == NULL)
538
0
        PyErr_Clear();
539
0
    encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
540
    /* Reset position */
541
0
    if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
542
0
        Py_DECREF(io);
543
0
        Py_DECREF(binary);
544
0
        PyMem_Free(found_encoding);
545
0
        return 0;
546
0
    }
547
0
    fob = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper),
548
0
                               "Os", binary, encoding);
549
0
    Py_DECREF(io);
550
0
    PyMem_Free(found_encoding);
551
552
0
    if (fob == NULL) {
553
0
        PyErr_Clear();
554
555
0
        res = PyObject_CallMethodNoArgs(binary, &_Py_ID(close));
556
0
        Py_DECREF(binary);
557
0
        if (res)
558
0
            Py_DECREF(res);
559
0
        else
560
0
            PyErr_Clear();
561
0
        return 0;
562
0
    }
563
0
    Py_DECREF(binary);
564
565
    /* get the line number lineno */
566
0
    for (i = 0; i < lineno; i++) {
567
0
        Py_XDECREF(lineobj);
568
0
        lineobj = PyFile_GetLine(fob, -1);
569
0
        if (!lineobj) {
570
0
            PyErr_Clear();
571
0
            break;
572
0
        }
573
0
    }
574
0
    res = PyObject_CallMethodNoArgs(fob, &_Py_ID(close));
575
0
    if (res) {
576
0
        Py_DECREF(res);
577
0
    }
578
0
    else {
579
0
        PyErr_Clear();
580
0
    }
581
0
    Py_DECREF(fob);
582
0
    if (!lineobj || !PyUnicode_Check(lineobj)) {
583
0
        Py_XDECREF(lineobj);
584
0
        return -1;
585
0
    }
586
587
0
    if (line) {
588
0
        *line = Py_NewRef(lineobj);
589
0
    }
590
591
    /* remove the indentation of the line */
592
0
    kind = PyUnicode_KIND(lineobj);
593
0
    data = PyUnicode_DATA(lineobj);
594
0
    for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
595
0
        Py_UCS4 ch = PyUnicode_READ(kind, data, i);
596
0
        if (ch != ' ' && ch != '\t' && ch != '\014')
597
0
            break;
598
0
    }
599
0
    if (i) {
600
0
        PyObject *truncated;
601
0
        truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
602
0
        if (truncated) {
603
0
            Py_SETREF(lineobj, truncated);
604
0
        } else {
605
0
            PyErr_Clear();
606
0
        }
607
0
    }
608
609
0
    if (truncation != NULL) {
610
0
        *truncation = i - indent;
611
0
    }
612
613
    /* Write some spaces before the line */
614
0
    if (_Py_WriteIndent(indent, f) < 0) {
615
0
        goto error;
616
0
    }
617
618
    /* finally display the line */
619
0
    if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {
620
0
        goto error;
621
0
    }
622
623
0
    if (PyFile_WriteString("\n", f) < 0) {
624
0
        goto error;
625
0
    }
626
627
0
    Py_DECREF(lineobj);
628
0
    return 0;
629
0
error:
630
0
    Py_DECREF(lineobj);
631
0
    return -1;
632
0
}
633
634
int
635
_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,
636
                      int *truncation, PyObject **line)
637
0
{
638
0
    return display_source_line(f, filename, lineno, indent, truncation, line);
639
0
}
640
641
642
#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\f'))
643
0
#define _TRACEBACK_SOURCE_LINE_INDENT 4
644
645
static inline int
646
0
ignore_source_errors(void) {
647
0
    if (PyErr_Occurred()) {
648
0
        if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
649
0
            return -1;
650
0
        }
651
0
        PyErr_Clear();
652
0
    }
653
0
    return 0;
654
0
}
655
656
static int
657
tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,
658
               PyFrameObject *frame, PyObject *name)
659
0
{
660
0
    if (filename == NULL || name == NULL) {
661
0
        return -1;
662
0
    }
663
664
0
    PyObject *line = PyUnicode_FromFormat("  File \"%U\", line %d, in %U\n",
665
0
                                          filename, lineno, name);
666
0
    if (line == NULL) {
667
0
        return -1;
668
0
    }
669
670
0
    int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);
671
0
    Py_DECREF(line);
672
0
    if (res < 0) {
673
0
        return -1;
674
0
    }
675
676
0
    int err = 0;
677
678
0
    int truncation = _TRACEBACK_SOURCE_LINE_INDENT;
679
0
    PyObject* source_line = NULL;
680
0
    int rc = display_source_line(
681
0
            f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT,
682
0
            &truncation, &source_line);
683
0
    if (rc != 0 || !source_line) {
684
        /* ignore errors since we can't report them, can we? */
685
0
        err = ignore_source_errors();
686
0
    }
687
0
    Py_XDECREF(source_line);
688
0
    return err;
689
0
}
690
691
static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
692
693
static int
694
tb_print_line_repeated(PyObject *f, long cnt)
695
0
{
696
0
    cnt -= TB_RECURSIVE_CUTOFF;
697
0
    PyObject *line = PyUnicode_FromFormat(
698
0
        (cnt > 1)
699
0
          ? "  [Previous line repeated %ld more times]\n"
700
0
          : "  [Previous line repeated %ld more time]\n",
701
0
        cnt);
702
0
    if (line == NULL) {
703
0
        return -1;
704
0
    }
705
0
    int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
706
0
    Py_DECREF(line);
707
0
    return err;
708
0
}
709
710
static int
711
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
712
0
{
713
0
    PyCodeObject *code = NULL;
714
0
    Py_ssize_t depth = 0;
715
0
    PyObject *last_file = NULL;
716
0
    int last_line = -1;
717
0
    PyObject *last_name = NULL;
718
0
    long cnt = 0;
719
0
    PyTracebackObject *tb1 = tb;
720
0
    while (tb1 != NULL) {
721
0
        depth++;
722
0
        tb1 = tb1->tb_next;
723
0
    }
724
0
    while (tb != NULL && depth > limit) {
725
0
        depth--;
726
0
        tb = tb->tb_next;
727
0
    }
728
0
    while (tb != NULL) {
729
0
        code = PyFrame_GetCode(tb->tb_frame);
730
0
        int tb_lineno = tb->tb_lineno;
731
0
        if (tb_lineno == -1) {
732
0
            tb_lineno = tb_get_lineno((PyObject *)tb);
733
0
        }
734
0
        if (last_file == NULL ||
735
0
            code->co_filename != last_file ||
736
0
            last_line == -1 || tb_lineno != last_line ||
737
0
            last_name == NULL || code->co_name != last_name) {
738
0
            if (cnt > TB_RECURSIVE_CUTOFF) {
739
0
                if (tb_print_line_repeated(f, cnt) < 0) {
740
0
                    goto error;
741
0
                }
742
0
            }
743
0
            last_file = code->co_filename;
744
0
            last_line = tb_lineno;
745
0
            last_name = code->co_name;
746
0
            cnt = 0;
747
0
        }
748
0
        cnt++;
749
0
        if (cnt <= TB_RECURSIVE_CUTOFF) {
750
0
            if (tb_displayline(tb, f, code->co_filename, tb_lineno,
751
0
                               tb->tb_frame, code->co_name) < 0) {
752
0
                goto error;
753
0
            }
754
755
0
            if (PyErr_CheckSignals() < 0) {
756
0
                goto error;
757
0
            }
758
0
        }
759
0
        Py_CLEAR(code);
760
0
        tb = tb->tb_next;
761
0
    }
762
0
    if (cnt > TB_RECURSIVE_CUTOFF) {
763
0
        if (tb_print_line_repeated(f, cnt) < 0) {
764
0
            goto error;
765
0
        }
766
0
    }
767
0
    return 0;
768
0
error:
769
0
    Py_XDECREF(code);
770
0
    return -1;
771
0
}
772
773
0
#define PyTraceBack_LIMIT 1000
774
775
int
776
_PyTraceBack_Print(PyObject *v, const char *header, PyObject *f)
777
0
{
778
0
    PyObject *limitv;
779
0
    long limit = PyTraceBack_LIMIT;
780
781
0
    if (v == NULL) {
782
0
        return 0;
783
0
    }
784
0
    if (!PyTraceBack_Check(v)) {
785
0
        PyErr_BadInternalCall();
786
0
        return -1;
787
0
    }
788
0
    if (PySys_GetOptionalAttrString("tracebacklimit", &limitv) < 0) {
789
0
        return -1;
790
0
    }
791
0
    else if (limitv != NULL && PyLong_Check(limitv)) {
792
0
        int overflow;
793
0
        limit = PyLong_AsLongAndOverflow(limitv, &overflow);
794
0
        if (overflow > 0) {
795
0
            limit = LONG_MAX;
796
0
        }
797
0
        else if (limit <= 0) {
798
0
            Py_DECREF(limitv);
799
0
            return 0;
800
0
        }
801
0
    }
802
0
    Py_XDECREF(limitv);
803
804
0
    if (PyFile_WriteString(header, f) < 0) {
805
0
        return -1;
806
0
    }
807
808
0
    if (tb_printinternal((PyTracebackObject *)v, f, limit) < 0) {
809
0
        return -1;
810
0
    }
811
812
0
    return 0;
813
0
}
814
815
int
816
PyTraceBack_Print(PyObject *v, PyObject *f)
817
0
{
818
0
    const char *header = EXCEPTION_TB_HEADER;
819
0
    return _PyTraceBack_Print(v, header, f);
820
0
}
821
822
/* Format an integer in range [0; 0xffffffff] to decimal and write it
823
   into the file fd.
824
825
   This function is signal safe. */
826
827
void
828
_Py_DumpDecimal(int fd, size_t value)
829
0
{
830
    /* maximum number of characters required for output of %lld or %p.
831
       We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
832
       plus 1 for the null byte.  53/22 is an upper bound for log10(256). */
833
0
    char buffer[1 + (sizeof(size_t)*53-1) / 22 + 1];
834
0
    char *ptr, *end;
835
836
0
    end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
837
0
    ptr = end;
838
0
    *ptr = '\0';
839
0
    do {
840
0
        --ptr;
841
0
        assert(ptr >= buffer);
842
0
        *ptr = '0' + (value % 10);
843
0
        value /= 10;
844
0
    } while (value);
845
846
0
    (void)_Py_write_noraise(fd, ptr, end - ptr);
847
0
}
848
849
/* Format an integer as hexadecimal with width digits into fd file descriptor.
850
   The function is signal safe. */
851
static void
852
dump_hexadecimal(int fd, uintptr_t value, Py_ssize_t width, int strip_zeros)
853
0
{
854
0
    char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end;
855
0
    Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
856
857
0
    if (width > size)
858
0
        width = size;
859
    /* it's ok if width is negative */
860
861
0
    end = &buffer[size];
862
0
    ptr = end;
863
0
    *ptr = '\0';
864
0
    do {
865
0
        --ptr;
866
0
        assert(ptr >= buffer);
867
0
        *ptr = Py_hexdigits[value & 15];
868
0
        value >>= 4;
869
0
    } while ((end - ptr) < width || value);
870
871
0
    size = end - ptr;
872
0
    if (strip_zeros) {
873
0
        while (*ptr == '0' && size >= 2) {
874
0
            ptr++;
875
0
            size--;
876
0
        }
877
0
    }
878
879
0
    (void)_Py_write_noraise(fd, ptr, size);
880
0
}
881
882
void
883
_Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width)
884
0
{
885
0
    dump_hexadecimal(fd, value, width, 0);
886
0
}
887
888
#ifdef CAN_C_BACKTRACE
889
static void
890
dump_pointer(int fd, void *ptr)
891
0
{
892
0
    PUTS(fd, "0x");
893
0
    dump_hexadecimal(fd, (uintptr_t)ptr, sizeof(void*), 1);
894
0
}
895
#endif
896
897
static void
898
dump_char(int fd, char ch)
899
0
{
900
0
    char buf[1] = {ch};
901
0
    (void)_Py_write_noraise(fd, buf, 1);
902
0
}
903
904
void
905
_Py_DumpASCII(int fd, PyObject *text)
906
0
{
907
0
    PyASCIIObject *ascii = _PyASCIIObject_CAST(text);
908
0
    Py_ssize_t i, size;
909
0
    int truncated;
910
0
    int kind;
911
0
    void *data = NULL;
912
0
    Py_UCS4 ch;
913
914
0
    if (!PyUnicode_Check(text))
915
0
        return;
916
917
0
    size = ascii->length;
918
0
    kind = ascii->state.kind;
919
0
    if (ascii->state.compact) {
920
0
        if (ascii->state.ascii)
921
0
            data = ascii + 1;
922
0
        else
923
0
            data = _PyCompactUnicodeObject_CAST(text) + 1;
924
0
    }
925
0
    else {
926
0
        data = _PyUnicodeObject_CAST(text)->data.any;
927
0
        if (data == NULL)
928
0
            return;
929
0
    }
930
931
0
    if (MAX_STRING_LENGTH < size) {
932
0
        size = MAX_STRING_LENGTH;
933
0
        truncated = 1;
934
0
    }
935
0
    else {
936
0
        truncated = 0;
937
0
    }
938
939
    // Is an ASCII string?
940
0
    if (ascii->state.ascii) {
941
0
        assert(kind == PyUnicode_1BYTE_KIND);
942
0
        char *str = data;
943
944
0
        int need_escape = 0;
945
0
        for (i=0; i < size; i++) {
946
0
            ch = str[i];
947
0
            if (!(' ' <= ch && ch <= 126)) {
948
0
                need_escape = 1;
949
0
                break;
950
0
            }
951
0
        }
952
0
        if (!need_escape) {
953
            // The string can be written with a single write() syscall
954
0
            (void)_Py_write_noraise(fd, str, size);
955
0
            goto done;
956
0
        }
957
0
    }
958
959
0
    for (i=0; i < size; i++) {
960
0
        ch = PyUnicode_READ(kind, data, i);
961
0
        if (' ' <= ch && ch <= 126) {
962
            /* printable ASCII character */
963
0
            dump_char(fd, (char)ch);
964
0
        }
965
0
        else if (ch <= 0xff) {
966
0
            PUTS(fd, "\\x");
967
0
            _Py_DumpHexadecimal(fd, ch, 2);
968
0
        }
969
0
        else if (ch <= 0xffff) {
970
0
            PUTS(fd, "\\u");
971
0
            _Py_DumpHexadecimal(fd, ch, 4);
972
0
        }
973
0
        else {
974
0
            PUTS(fd, "\\U");
975
0
            _Py_DumpHexadecimal(fd, ch, 8);
976
0
        }
977
0
    }
978
979
0
done:
980
0
    if (truncated) {
981
0
        PUTS(fd, "...");
982
0
    }
983
0
}
984
985
986
#ifdef MS_WINDOWS
987
static void
988
_Py_DumpWideString(int fd, wchar_t *str)
989
{
990
    Py_ssize_t size = wcslen(str);
991
    int truncated;
992
    if (MAX_STRING_LENGTH < size) {
993
        size = MAX_STRING_LENGTH;
994
        truncated = 1;
995
    }
996
    else {
997
        truncated = 0;
998
    }
999
1000
    for (Py_ssize_t i=0; i < size; i++) {
1001
        Py_UCS4 ch = str[i];
1002
        if (' ' <= ch && ch <= 126) {
1003
            /* printable ASCII character */
1004
            dump_char(fd, (char)ch);
1005
        }
1006
        else if (ch <= 0xff) {
1007
            PUTS(fd, "\\x");
1008
            _Py_DumpHexadecimal(fd, ch, 2);
1009
        }
1010
        else if (Py_UNICODE_IS_HIGH_SURROGATE(ch)
1011
                 && Py_UNICODE_IS_LOW_SURROGATE(str[i+1])) {
1012
            ch = Py_UNICODE_JOIN_SURROGATES(ch, str[i+1]);
1013
            i++;  // Skip the low surrogate character
1014
            PUTS(fd, "\\U");
1015
            _Py_DumpHexadecimal(fd, ch, 8);
1016
        }
1017
        else {
1018
            Py_BUILD_ASSERT(sizeof(wchar_t) == 2);
1019
            PUTS(fd, "\\u");
1020
            _Py_DumpHexadecimal(fd, ch, 4);
1021
        }
1022
    }
1023
1024
    if (truncated) {
1025
        PUTS(fd, "...");
1026
    }
1027
}
1028
#endif
1029
1030
1031
/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
1032
1033
   This function is signal safe.
1034
1035
   Return 0 on success. Return -1 if the frame is invalid. */
1036
1037
static int _Py_NO_SANITIZE_THREAD
1038
dump_frame(int fd, _PyInterpreterFrame *frame)
1039
0
{
1040
0
    if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
1041
        /* Ignore trampoline frames and base frame sentinel */
1042
0
        return 0;
1043
0
    }
1044
1045
0
    PyCodeObject *code = _PyFrame_SafeGetCode(frame);
1046
0
    if (code == NULL) {
1047
0
        return -1;
1048
0
    }
1049
1050
0
    int res = 0;
1051
0
    PUTS(fd, "  File ");
1052
0
    if (code->co_filename != NULL
1053
0
        && PyUnicode_Check(code->co_filename))
1054
0
    {
1055
0
        PUTS(fd, "\"");
1056
0
        _Py_DumpASCII(fd, code->co_filename);
1057
0
        PUTS(fd, "\"");
1058
0
    }
1059
0
    else {
1060
0
        PUTS(fd, "???");
1061
0
        res = -1;
1062
0
    }
1063
1064
0
    PUTS(fd, ", line ");
1065
0
    int lasti = _PyFrame_SafeGetLasti(frame);
1066
0
    int lineno = -1;
1067
0
    if (lasti >= 0) {
1068
0
        lineno = _PyCode_SafeAddr2Line(code, lasti);
1069
0
    }
1070
0
    if (lineno >= 0) {
1071
0
        _Py_DumpDecimal(fd, (size_t)lineno);
1072
0
    }
1073
0
    else {
1074
0
        PUTS(fd, "???");
1075
0
        res = -1;
1076
0
    }
1077
1078
0
    PUTS(fd, " in ");
1079
0
    if (code->co_name != NULL && PyUnicode_Check(code->co_name)) {
1080
0
        _Py_DumpASCII(fd, code->co_name);
1081
0
    }
1082
0
    else {
1083
0
        PUTS(fd, "???");
1084
0
        res = -1;
1085
0
    }
1086
0
    PUTS(fd, "\n");
1087
0
    return res;
1088
0
}
1089
1090
static int _Py_NO_SANITIZE_THREAD
1091
tstate_is_freed(PyThreadState *tstate)
1092
0
{
1093
0
    if (_PyMem_IsPtrFreed(tstate)) {
1094
0
        return 1;
1095
0
    }
1096
0
    if (_PyMem_IsPtrFreed(tstate->interp)) {
1097
0
        return 1;
1098
0
    }
1099
0
    if (_PyMem_IsULongFreed(tstate->thread_id)) {
1100
0
        return 1;
1101
0
    }
1102
0
    return 0;
1103
0
}
1104
1105
1106
static int _Py_NO_SANITIZE_THREAD
1107
interp_is_freed(PyInterpreterState *interp)
1108
0
{
1109
0
    return _PyMem_IsPtrFreed(interp);
1110
0
}
1111
1112
1113
static void _Py_NO_SANITIZE_THREAD
1114
dump_traceback(int fd, PyThreadState *tstate, int write_header)
1115
0
{
1116
0
    if (write_header) {
1117
0
        PUTS(fd, "Stack (most recent call first):\n");
1118
0
    }
1119
1120
0
    if (tstate_is_freed(tstate)) {
1121
0
        PUTS(fd, "  <freed thread state>\n");
1122
0
        return;
1123
0
    }
1124
1125
0
    _PyInterpreterFrame *frame = tstate->current_frame;
1126
0
    if (frame == NULL) {
1127
0
        PUTS(fd, "  <no Python frame>\n");
1128
0
        return;
1129
0
    }
1130
1131
0
    unsigned int depth = 0;
1132
0
    while (1) {
1133
0
        if (MAX_FRAME_DEPTH <= depth) {
1134
0
            if (MAX_FRAME_DEPTH < depth) {
1135
0
                PUTS(fd, "plus ");
1136
0
                _Py_DumpDecimal(fd, depth);
1137
0
                PUTS(fd, " frames\n");
1138
0
            }
1139
0
            break;
1140
0
        }
1141
1142
0
        if (_PyMem_IsPtrFreed(frame)) {
1143
0
            PUTS(fd, "  <freed frame>\n");
1144
0
            break;
1145
0
        }
1146
        // Read frame->previous early since memory can be freed during
1147
        // dump_frame()
1148
0
        _PyInterpreterFrame *previous = frame->previous;
1149
1150
0
        if (dump_frame(fd, frame) < 0) {
1151
0
            PUTS(fd, "  <invalid frame>\n");
1152
0
            break;
1153
0
        }
1154
1155
0
        frame = previous;
1156
0
        if (frame == NULL) {
1157
0
            break;
1158
0
        }
1159
0
        depth++;
1160
0
    }
1161
0
}
1162
1163
/* Dump the traceback of a Python thread into fd. Use write() to write the
1164
   traceback and retry if write() is interrupted by a signal (failed with
1165
   EINTR), but don't call the Python signal handler.
1166
1167
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1168
   handlers if signals were received. */
1169
const char*
1170
PyUnstable_DumpTraceback(int fd, PyThreadState *tstate)
1171
0
{
1172
0
    dump_traceback(fd, tstate, 1);
1173
0
    return NULL;
1174
0
}
1175
1176
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1177
# if defined(__OpenBSD__)
1178
    /* pthread_*_np functions, especially pthread_{get,set}_name_np().
1179
       pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
1180
       pthread_getname_np() and pthread_setname_np() in pthread.h as long as
1181
       __BSD_VISIBLE remains set.
1182
     */
1183
#   include <pthread_np.h>
1184
# endif
1185
#endif
1186
1187
1188
// Write the thread name
1189
static void _Py_NO_SANITIZE_THREAD
1190
write_thread_name(int fd, PyThreadState *tstate)
1191
0
{
1192
0
#ifndef MS_WINDOWS
1193
0
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
1194
0
    char name[100];
1195
0
    pthread_t thread = (pthread_t)tstate->thread_id;
1196
0
#ifdef HAVE_PTHREAD_GETNAME_NP
1197
0
    int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
1198
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
1199
    int rc = 0; /* pthread_get_name_np() returns void */
1200
    pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
1201
#endif
1202
0
    if (!rc) {
1203
0
        size_t len = strlen(name);
1204
0
        if (len) {
1205
0
            PUTS(fd, " [");
1206
0
            (void)_Py_write_noraise(fd, name, len);
1207
0
            PUTS(fd, "]");
1208
0
        }
1209
0
    }
1210
0
#endif
1211
#else
1212
    // Windows implementation
1213
    if (pGetThreadDescription == NULL) {
1214
        return;
1215
    }
1216
1217
    HANDLE thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, tstate->thread_id);
1218
    if (thread == NULL) {
1219
        return;
1220
    }
1221
1222
    wchar_t *name;
1223
    HRESULT hr = pGetThreadDescription(thread, &name);
1224
    if (!FAILED(hr)) {
1225
        if (name[0] != 0) {
1226
            PUTS(fd, " [");
1227
            _Py_DumpWideString(fd, name);
1228
            PUTS(fd, "]");
1229
        }
1230
        LocalFree(name);
1231
    }
1232
    CloseHandle(thread);
1233
#endif
1234
0
}
1235
1236
1237
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
1238
   is_current is true, "Thread 0xHHHH:\n" otherwise.
1239
1240
   This function is signal safe (except on Windows). */
1241
1242
static void _Py_NO_SANITIZE_THREAD
1243
write_thread_id(int fd, PyThreadState *tstate, int is_current)
1244
0
{
1245
0
    if (is_current)
1246
0
        PUTS(fd, "Current thread 0x");
1247
0
    else
1248
0
        PUTS(fd, "Thread 0x");
1249
0
    _Py_DumpHexadecimal(fd,
1250
0
                        tstate->thread_id,
1251
0
                        sizeof(unsigned long) * 2);
1252
1253
0
    if (!_PyMem_IsULongFreed(tstate->thread_id)) {
1254
0
        write_thread_name(fd, tstate);
1255
0
    }
1256
1257
0
    PUTS(fd, " (most recent call first):\n");
1258
0
}
1259
1260
/* Dump the traceback of all Python threads into fd. Use write() to write the
1261
   traceback and retry if write() is interrupted by a signal (failed with
1262
   EINTR), but don't call the Python signal handler.
1263
1264
   The caller is responsible to call PyErr_CheckSignals() to call Python signal
1265
   handlers if signals were received. */
1266
const char* _Py_NO_SANITIZE_THREAD
1267
PyUnstable_DumpTracebackThreads(int fd, PyInterpreterState *interp,
1268
                                PyThreadState *current_tstate,
1269
                                Py_ssize_t max_threads)
1270
0
{
1271
0
    if (max_threads == 0) {
1272
0
        max_threads = DEFAULT_MAX_NTHREADS;
1273
0
    }
1274
1275
0
    if (current_tstate == NULL) {
1276
        /* PyUnstable_DumpTracebackThreads() is called from signal handlers by
1277
           faulthandler.
1278
1279
           SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
1280
           and are thus delivered to the thread that caused the fault. Get the
1281
           Python thread state of the current thread.
1282
1283
           PyThreadState_Get() doesn't give the state of the thread that caused
1284
           the fault if the thread released the GIL, and so
1285
           _PyThreadState_GET() cannot be used. Read the thread specific
1286
           storage (TSS) instead: call PyGILState_GetThisThreadState(). */
1287
0
        current_tstate = PyGILState_GetThisThreadState();
1288
0
    }
1289
1290
0
    if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
1291
0
        return "tstate is freed";
1292
0
    }
1293
1294
0
    if (interp == NULL) {
1295
0
        if (current_tstate == NULL) {
1296
0
            interp = _PyGILState_GetInterpreterStateUnsafe();
1297
0
            if (interp == NULL) {
1298
                /* We need the interpreter state to get Python threads */
1299
0
                return "unable to get the interpreter state";
1300
0
            }
1301
0
        }
1302
0
        else {
1303
0
            interp = current_tstate->interp;
1304
0
        }
1305
0
    }
1306
0
    assert(interp != NULL);
1307
1308
0
    if (interp_is_freed(interp)) {
1309
0
        return "interp is freed";
1310
0
    }
1311
1312
    /* Get the current interpreter from the current thread */
1313
0
    PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
1314
0
    if (tstate == NULL)
1315
0
        return "unable to get the thread head state";
1316
1317
    /* Dump the traceback of each thread */
1318
0
    Py_ssize_t nthreads = 0;
1319
0
    _Py_BEGIN_SUPPRESS_IPH
1320
0
    do
1321
0
    {
1322
0
        if (nthreads != 0)
1323
0
            PUTS(fd, "\n");
1324
0
        if (nthreads >= max_threads) {
1325
0
            PUTS(fd, "...\n");
1326
0
            break;
1327
0
        }
1328
1329
0
        if (tstate_is_freed(tstate)) {
1330
0
            PUTS(fd, "<freed thread state>\n");
1331
0
            break;
1332
0
        }
1333
1334
0
        write_thread_id(fd, tstate, tstate == current_tstate);
1335
0
        if (tstate == current_tstate && tstate->interp->gc.collecting) {
1336
0
            PUTS(fd, "  Garbage-collecting\n");
1337
0
        }
1338
0
        dump_traceback(fd, tstate, 0);
1339
1340
0
        tstate = tstate->next;
1341
0
        nthreads++;
1342
0
    } while (tstate != NULL);
1343
0
    _Py_END_SUPPRESS_IPH
1344
1345
0
    return NULL;
1346
0
}
1347
1348
#ifdef CAN_C_BACKTRACE
1349
/* Based on glibc's implementation of backtrace_symbols(), but only uses stack memory. */
1350
void
1351
_Py_backtrace_symbols_fd(int fd, void *const *array, Py_ssize_t size)
1352
0
{
1353
0
    VLA(Dl_info, info, size);
1354
0
    VLA(int, status, size);
1355
    /* Fill in the information we can get from dladdr() */
1356
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1357
#ifdef __APPLE__
1358
        status[i] = dladdr(array[i], &info[i]);
1359
#else
1360
0
        struct link_map *map;
1361
0
        status[i] = dladdr1(array[i], &info[i], (void **)&map, RTLD_DL_LINKMAP);
1362
0
        if (status[i] != 0
1363
0
            && info[i].dli_fname != NULL
1364
0
            && info[i].dli_fname[0] != '\0') {
1365
            /* The load bias is more useful to the user than the load
1366
               address. The use of these addresses is to calculate an
1367
               address in the ELF file, so its prelinked bias is not
1368
               something we want to subtract out */
1369
0
            info[i].dli_fbase = (void *) map->l_addr;
1370
0
        }
1371
0
#endif
1372
0
    }
1373
0
    for (Py_ssize_t i = 0; i < size; ++i) {
1374
0
        if (status[i] == 0
1375
0
            || info[i].dli_fname == NULL
1376
0
            || info[i].dli_fname[0] == '\0'
1377
0
        ) {
1378
0
            PUTS(fd, "  Binary file '<unknown>' [");
1379
0
            dump_pointer(fd, array[i]);
1380
0
            PUTS(fd, "]\n");
1381
0
            continue;
1382
0
        }
1383
1384
0
        if (info[i].dli_sname == NULL) {
1385
            /* We found no symbol name to use, so describe it as
1386
               relative to the file. */
1387
0
            info[i].dli_saddr = info[i].dli_fbase;
1388
0
        }
1389
1390
0
        if (info[i].dli_sname == NULL && info[i].dli_saddr == 0) {
1391
0
            PUTS(fd, "  Binary file \"");
1392
0
            PUTS(fd, info[i].dli_fname);
1393
0
            PUTS(fd, "\" [");
1394
0
            dump_pointer(fd, array[i]);
1395
0
            PUTS(fd, "]\n");
1396
0
        }
1397
0
        else {
1398
0
            char sign;
1399
0
            ptrdiff_t offset;
1400
0
            if (array[i] >= (void *) info[i].dli_saddr) {
1401
0
                sign = '+';
1402
0
                offset = array[i] - info[i].dli_saddr;
1403
0
            }
1404
0
            else {
1405
0
                sign = '-';
1406
0
                offset = info[i].dli_saddr - array[i];
1407
0
            }
1408
0
            const char *symbol_name = info[i].dli_sname != NULL ? info[i].dli_sname : "";
1409
0
            PUTS(fd, "  Binary file \"");
1410
0
            PUTS(fd, info[i].dli_fname);
1411
0
            PUTS(fd, "\", at ");
1412
0
            PUTS(fd, symbol_name);
1413
0
            dump_char(fd, sign);
1414
0
            PUTS(fd, "0x");
1415
0
            dump_hexadecimal(fd, offset, sizeof(offset), 1);
1416
0
            PUTS(fd, " [");
1417
0
            dump_pointer(fd, array[i]);
1418
0
            PUTS(fd, "]\n");
1419
0
        }
1420
0
    }
1421
0
}
1422
1423
void
1424
_Py_DumpStack(int fd)
1425
0
{
1426
0
#define BACKTRACE_SIZE 32
1427
0
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1428
0
    VLA(void *, callstack, BACKTRACE_SIZE);
1429
0
    int frames = backtrace(callstack, BACKTRACE_SIZE);
1430
0
    if (frames == 0) {
1431
        // Some systems won't return anything for the stack trace
1432
0
        PUTS(fd, "  <system returned no stack trace>\n");
1433
0
        return;
1434
0
    }
1435
1436
0
    _Py_backtrace_symbols_fd(fd, callstack, frames);
1437
0
    if (frames == BACKTRACE_SIZE) {
1438
0
        PUTS(fd, "  <truncated rest of calls>\n");
1439
0
    }
1440
1441
0
#undef BACKTRACE_SIZE
1442
0
}
1443
#else
1444
void
1445
_Py_DumpStack(int fd)
1446
{
1447
    PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
1448
    PUTS(fd, "  <cannot get C stack on this system>\n");
1449
}
1450
#endif
1451
1452
void
1453
_Py_InitDumpStack(void)
1454
0
{
1455
0
#ifdef CAN_C_BACKTRACE
1456
    // gh-137185: Call backtrace() once to force libgcc to be loaded early.
1457
0
    void *callstack[1];
1458
0
    (void)backtrace(callstack, 1);
1459
0
#endif
1460
0
}
1461
1462
1463
void
1464
_Py_DumpTraceback_Init(void)
1465
21
{
1466
#ifdef MS_WINDOWS
1467
    if (pGetThreadDescription != NULL) {
1468
        return;
1469
    }
1470
1471
    HMODULE kernelbase = GetModuleHandleW(L"kernelbase.dll");
1472
    if (kernelbase != NULL) {
1473
        pGetThreadDescription = (PF_GET_THREAD_DESCRIPTION)GetProcAddress(
1474
                                    kernelbase, "GetThreadDescription");
1475
    }
1476
#endif
1477
21
}