Coverage Report

Created: 2025-11-30 06:38

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