Home | History | Annotate | Download | only in Python
      1 
      2 /* Traceback implementation */
      3 
      4 #include "Python.h"
      5 
      6 #include "code.h"
      7 #include "frameobject.h"
      8 #include "structmember.h"
      9 #include "osdefs.h"
     10 #ifdef HAVE_FCNTL_H
     11 #include <fcntl.h>
     12 #endif
     13 
     14 #define OFF(x) offsetof(PyTracebackObject, x)
     15 
     16 #define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
     17 #define MAX_STRING_LENGTH 500
     18 #define MAX_FRAME_DEPTH 100
     19 #define MAX_NTHREADS 100
     20 
     21 /* Function from Parser/tokenizer.c */
     22 extern char * PyTokenizer_FindEncodingFilename(int, PyObject *);
     23 
     24 _Py_IDENTIFIER(TextIOWrapper);
     25 _Py_IDENTIFIER(close);
     26 _Py_IDENTIFIER(open);
     27 _Py_IDENTIFIER(path);
     28 
     29 static PyObject *
     30 tb_dir(PyTracebackObject *self)
     31 {
     32     return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
     33                                    "tb_lasti", "tb_lineno");
     34 }
     35 
     36 static PyMethodDef tb_methods[] = {
     37    {"__dir__", (PyCFunction)tb_dir, METH_NOARGS},
     38    {NULL, NULL, 0, NULL},
     39 };
     40 
     41 static PyMemberDef tb_memberlist[] = {
     42     {"tb_next",         T_OBJECT,       OFF(tb_next),   READONLY},
     43     {"tb_frame",        T_OBJECT,       OFF(tb_frame),  READONLY},
     44     {"tb_lasti",        T_INT,          OFF(tb_lasti),  READONLY},
     45     {"tb_lineno",       T_INT,          OFF(tb_lineno), READONLY},
     46     {NULL}      /* Sentinel */
     47 };
     48 
     49 static void
     50 tb_dealloc(PyTracebackObject *tb)
     51 {
     52     PyObject_GC_UnTrack(tb);
     53     Py_TRASHCAN_SAFE_BEGIN(tb)
     54     Py_XDECREF(tb->tb_next);
     55     Py_XDECREF(tb->tb_frame);
     56     PyObject_GC_Del(tb);
     57     Py_TRASHCAN_SAFE_END(tb)
     58 }
     59 
     60 static int
     61 tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
     62 {
     63     Py_VISIT(tb->tb_next);
     64     Py_VISIT(tb->tb_frame);
     65     return 0;
     66 }
     67 
     68 static void
     69 tb_clear(PyTracebackObject *tb)
     70 {
     71     Py_CLEAR(tb->tb_next);
     72     Py_CLEAR(tb->tb_frame);
     73 }
     74 
     75 PyTypeObject PyTraceBack_Type = {
     76     PyVarObject_HEAD_INIT(&PyType_Type, 0)
     77     "traceback",
     78     sizeof(PyTracebackObject),
     79     0,
     80     (destructor)tb_dealloc, /*tp_dealloc*/
     81     0,                  /*tp_print*/
     82     0,    /*tp_getattr*/
     83     0,                  /*tp_setattr*/
     84     0,                  /*tp_reserved*/
     85     0,                  /*tp_repr*/
     86     0,                  /*tp_as_number*/
     87     0,                  /*tp_as_sequence*/
     88     0,                  /*tp_as_mapping*/
     89     0,                  /* tp_hash */
     90     0,                  /* tp_call */
     91     0,                  /* tp_str */
     92     PyObject_GenericGetAttr,                    /* tp_getattro */
     93     0,                  /* tp_setattro */
     94     0,                                          /* tp_as_buffer */
     95     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
     96     0,                                          /* tp_doc */
     97     (traverseproc)tb_traverse,                  /* tp_traverse */
     98     (inquiry)tb_clear,                          /* tp_clear */
     99     0,                                          /* tp_richcompare */
    100     0,                                          /* tp_weaklistoffset */
    101     0,                                          /* tp_iter */
    102     0,                                          /* tp_iternext */
    103     tb_methods,         /* tp_methods */
    104     tb_memberlist,      /* tp_members */
    105     0,                                          /* tp_getset */
    106     0,                                          /* tp_base */
    107     0,                                          /* tp_dict */
    108 };
    109 
    110 static PyTracebackObject *
    111 newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
    112 {
    113     PyTracebackObject *tb;
    114     if ((next != NULL && !PyTraceBack_Check(next)) ||
    115                     frame == NULL || !PyFrame_Check(frame)) {
    116         PyErr_BadInternalCall();
    117         return NULL;
    118     }
    119     tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
    120     if (tb != NULL) {
    121         Py_XINCREF(next);
    122         tb->tb_next = next;
    123         Py_XINCREF(frame);
    124         tb->tb_frame = frame;
    125         tb->tb_lasti = frame->f_lasti;
    126         tb->tb_lineno = PyFrame_GetLineNumber(frame);
    127         PyObject_GC_Track(tb);
    128     }
    129     return tb;
    130 }
    131 
    132 int
    133 PyTraceBack_Here(PyFrameObject *frame)
    134 {
    135     PyObject *exc, *val, *tb, *newtb;
    136     PyErr_Fetch(&exc, &val, &tb);
    137     newtb = (PyObject *)newtracebackobject((PyTracebackObject *)tb, frame);
    138     if (newtb == NULL) {
    139         _PyErr_ChainExceptions(exc, val, tb);
    140         return -1;
    141     }
    142     PyErr_Restore(exc, val, newtb);
    143     Py_XDECREF(tb);
    144     return 0;
    145 }
    146 
    147 /* Insert a frame into the traceback for (funcname, filename, lineno). */
    148 void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
    149 {
    150     PyObject *globals;
    151     PyCodeObject *code;
    152     PyFrameObject *frame;
    153     PyObject *exc, *val, *tb;
    154 
    155     /* Save and clear the current exception. Python functions must not be
    156        called with an exception set. Calling Python functions happens when
    157        the codec of the filesystem encoding is implemented in pure Python. */
    158     PyErr_Fetch(&exc, &val, &tb);
    159 
    160     globals = PyDict_New();
    161     if (!globals)
    162         goto error;
    163     code = PyCode_NewEmpty(filename, funcname, lineno);
    164     if (!code) {
    165         Py_DECREF(globals);
    166         goto error;
    167     }
    168     frame = PyFrame_New(PyThreadState_Get(), code, globals, NULL);
    169     Py_DECREF(globals);
    170     Py_DECREF(code);
    171     if (!frame)
    172         goto error;
    173     frame->f_lineno = lineno;
    174 
    175     PyErr_Restore(exc, val, tb);
    176     PyTraceBack_Here(frame);
    177     Py_DECREF(frame);
    178     return;
    179 
    180 error:
    181     _PyErr_ChainExceptions(exc, val, tb);
    182 }
    183 
    184 static PyObject *
    185 _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
    186 {
    187     Py_ssize_t i;
    188     PyObject *binary;
    189     PyObject *v;
    190     Py_ssize_t npath;
    191     size_t taillen;
    192     PyObject *syspath;
    193     PyObject *path;
    194     const char* tail;
    195     PyObject *filebytes;
    196     const char* filepath;
    197     Py_ssize_t len;
    198     PyObject* result;
    199 
    200     filebytes = PyUnicode_EncodeFSDefault(filename);
    201     if (filebytes == NULL) {
    202         PyErr_Clear();
    203         return NULL;
    204     }
    205     filepath = PyBytes_AS_STRING(filebytes);
    206 
    207     /* Search tail of filename in sys.path before giving up */
    208     tail = strrchr(filepath, SEP);
    209     if (tail == NULL)
    210         tail = filepath;
    211     else
    212         tail++;
    213     taillen = strlen(tail);
    214 
    215     syspath = _PySys_GetObjectId(&PyId_path);
    216     if (syspath == NULL || !PyList_Check(syspath))
    217         goto error;
    218     npath = PyList_Size(syspath);
    219 
    220     for (i = 0; i < npath; i++) {
    221         v = PyList_GetItem(syspath, i);
    222         if (v == NULL) {
    223             PyErr_Clear();
    224             break;
    225         }
    226         if (!PyUnicode_Check(v))
    227             continue;
    228         path = PyUnicode_EncodeFSDefault(v);
    229         if (path == NULL) {
    230             PyErr_Clear();
    231             continue;
    232         }
    233         len = PyBytes_GET_SIZE(path);
    234         if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
    235             Py_DECREF(path);
    236             continue; /* Too long */
    237         }
    238         strcpy(namebuf, PyBytes_AS_STRING(path));
    239         Py_DECREF(path);
    240         if (strlen(namebuf) != (size_t)len)
    241             continue; /* v contains '\0' */
    242         if (len > 0 && namebuf[len-1] != SEP)
    243             namebuf[len++] = SEP;
    244         strcpy(namebuf+len, tail);
    245 
    246         binary = _PyObject_CallMethodId(io, &PyId_open, "ss", namebuf, "rb");
    247         if (binary != NULL) {
    248             result = binary;
    249             goto finally;
    250         }
    251         PyErr_Clear();
    252     }
    253     goto error;
    254 
    255 error:
    256     result = NULL;
    257 finally:
    258     Py_DECREF(filebytes);
    259     return result;
    260 }
    261 
    262 int
    263 _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
    264 {
    265     int err = 0;
    266     int fd;
    267     int i;
    268     char *found_encoding;
    269     char *encoding;
    270     PyObject *io;
    271     PyObject *binary;
    272     PyObject *fob = NULL;
    273     PyObject *lineobj = NULL;
    274     PyObject *res;
    275     char buf[MAXPATHLEN+1];
    276     int kind;
    277     void *data;
    278 
    279     /* open the file */
    280     if (filename == NULL)
    281         return 0;
    282 
    283     io = PyImport_ImportModuleNoBlock("io");
    284     if (io == NULL)
    285         return -1;
    286     binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb");
    287 
    288     if (binary == NULL) {
    289         PyErr_Clear();
    290 
    291         binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
    292         if (binary == NULL) {
    293             Py_DECREF(io);
    294             return -1;
    295         }
    296     }
    297 
    298     /* use the right encoding to decode the file as unicode */
    299     fd = PyObject_AsFileDescriptor(binary);
    300     if (fd < 0) {
    301         Py_DECREF(io);
    302         Py_DECREF(binary);
    303         return 0;
    304     }
    305     found_encoding = PyTokenizer_FindEncodingFilename(fd, filename);
    306     if (found_encoding == NULL)
    307         PyErr_Clear();
    308     encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
    309     /* Reset position */
    310     if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
    311         Py_DECREF(io);
    312         Py_DECREF(binary);
    313         PyMem_FREE(found_encoding);
    314         return 0;
    315     }
    316     fob = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "Os", binary, encoding);
    317     Py_DECREF(io);
    318     PyMem_FREE(found_encoding);
    319 
    320     if (fob == NULL) {
    321         PyErr_Clear();
    322 
    323         res = _PyObject_CallMethodId(binary, &PyId_close, NULL);
    324         Py_DECREF(binary);
    325         if (res)
    326             Py_DECREF(res);
    327         else
    328             PyErr_Clear();
    329         return 0;
    330     }
    331     Py_DECREF(binary);
    332 
    333     /* get the line number lineno */
    334     for (i = 0; i < lineno; i++) {
    335         Py_XDECREF(lineobj);
    336         lineobj = PyFile_GetLine(fob, -1);
    337         if (!lineobj) {
    338             PyErr_Clear();
    339             err = -1;
    340             break;
    341         }
    342     }
    343     res = _PyObject_CallMethodId(fob, &PyId_close, NULL);
    344     if (res)
    345         Py_DECREF(res);
    346     else
    347         PyErr_Clear();
    348     Py_DECREF(fob);
    349     if (!lineobj || !PyUnicode_Check(lineobj)) {
    350         Py_XDECREF(lineobj);
    351         return err;
    352     }
    353 
    354     /* remove the indentation of the line */
    355     kind = PyUnicode_KIND(lineobj);
    356     data = PyUnicode_DATA(lineobj);
    357     for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
    358         Py_UCS4 ch = PyUnicode_READ(kind, data, i);
    359         if (ch != ' ' && ch != '\t' && ch != '\014')
    360             break;
    361     }
    362     if (i) {
    363         PyObject *truncated;
    364         truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
    365         if (truncated) {
    366             Py_DECREF(lineobj);
    367             lineobj = truncated;
    368         } else {
    369             PyErr_Clear();
    370         }
    371     }
    372 
    373     /* Write some spaces before the line */
    374     strcpy(buf, "          ");
    375     assert (strlen(buf) == 10);
    376     while (indent > 0) {
    377         if (indent < 10)
    378             buf[indent] = '\0';
    379         err = PyFile_WriteString(buf, f);
    380         if (err != 0)
    381             break;
    382         indent -= 10;
    383     }
    384 
    385     /* finally display the line */
    386     if (err == 0)
    387         err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW);
    388     Py_DECREF(lineobj);
    389     if  (err == 0)
    390         err = PyFile_WriteString("\n", f);
    391     return err;
    392 }
    393 
    394 static int
    395 tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name)
    396 {
    397     int err;
    398     PyObject *line;
    399 
    400     if (filename == NULL || name == NULL)
    401         return -1;
    402     line = PyUnicode_FromFormat("  File \"%U\", line %d, in %U\n",
    403                                 filename, lineno, name);
    404     if (line == NULL)
    405         return -1;
    406     err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
    407     Py_DECREF(line);
    408     if (err != 0)
    409         return err;
    410     /* ignore errors since we can't report them, can we? */
    411     if (_Py_DisplaySourceLine(f, filename, lineno, 4))
    412         PyErr_Clear();
    413     return err;
    414 }
    415 
    416 static int
    417 tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
    418 {
    419     int err = 0;
    420     long depth = 0;
    421     PyObject *last_file = NULL;
    422     int last_line = -1;
    423     PyObject *last_name = NULL;
    424     long cnt = 0;
    425     PyObject *line;
    426     PyTracebackObject *tb1 = tb;
    427     while (tb1 != NULL) {
    428         depth++;
    429         tb1 = tb1->tb_next;
    430     }
    431     while (tb != NULL && err == 0) {
    432         if (depth <= limit) {
    433             if (last_file != NULL &&
    434                 tb->tb_frame->f_code->co_filename == last_file &&
    435                 last_line != -1 && tb->tb_lineno == last_line &&
    436                 last_name != NULL &&
    437                 tb->tb_frame->f_code->co_name == last_name) {
    438                     cnt++;
    439                 } else {
    440                     if (cnt > 3) {
    441                         line = PyUnicode_FromFormat(
    442                         "  [Previous line repeated %d more times]\n", cnt-3);
    443                         err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
    444                         Py_DECREF(line);
    445                     }
    446                     last_file = tb->tb_frame->f_code->co_filename;
    447                     last_line = tb->tb_lineno;
    448                     last_name = tb->tb_frame->f_code->co_name;
    449                     cnt = 0;
    450                 }
    451             if (cnt < 3)
    452                 err = tb_displayline(f,
    453                                      tb->tb_frame->f_code->co_filename,
    454                                      tb->tb_lineno,
    455                                      tb->tb_frame->f_code->co_name);
    456         }
    457         depth--;
    458         tb = tb->tb_next;
    459         if (err == 0)
    460             err = PyErr_CheckSignals();
    461     }
    462     if (cnt > 3) {
    463         line = PyUnicode_FromFormat(
    464         "  [Previous line repeated %d more times]\n", cnt-3);
    465         err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
    466         Py_DECREF(line);
    467     }
    468     return err;
    469 }
    470 
    471 #define PyTraceBack_LIMIT 1000
    472 
    473 int
    474 PyTraceBack_Print(PyObject *v, PyObject *f)
    475 {
    476     int err;
    477     PyObject *limitv;
    478     long limit = PyTraceBack_LIMIT;
    479 
    480     if (v == NULL)
    481         return 0;
    482     if (!PyTraceBack_Check(v)) {
    483         PyErr_BadInternalCall();
    484         return -1;
    485     }
    486     limitv = PySys_GetObject("tracebacklimit");
    487     if (limitv) {
    488         PyObject *exc_type, *exc_value, *exc_tb;
    489 
    490         PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
    491         limit = PyLong_AsLong(limitv);
    492         if (limit == -1 && PyErr_Occurred()) {
    493             if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
    494                 limit = PyTraceBack_LIMIT;
    495             }
    496             else {
    497                 Py_XDECREF(exc_type);
    498                 Py_XDECREF(exc_value);
    499                 Py_XDECREF(exc_tb);
    500                 return 0;
    501             }
    502         }
    503         else if (limit <= 0) {
    504             limit = PyTraceBack_LIMIT;
    505         }
    506         PyErr_Restore(exc_type, exc_value, exc_tb);
    507     }
    508     err = PyFile_WriteString("Traceback (most recent call last):\n", f);
    509     if (!err)
    510         err = tb_printinternal((PyTracebackObject *)v, f, limit);
    511     return err;
    512 }
    513 
    514 /* Reverse a string. For example, "abcd" becomes "dcba".
    515 
    516    This function is signal safe. */
    517 
    518 void
    519 _Py_DumpDecimal(int fd, unsigned long value)
    520 {
    521     /* maximum number of characters required for output of %lld or %p.
    522        We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
    523        plus 1 for the null byte.  53/22 is an upper bound for log10(256). */
    524     char buffer[1 + (sizeof(unsigned long)*53-1) / 22 + 1];
    525     char *ptr, *end;
    526 
    527     end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
    528     ptr = end;
    529     *ptr = '\0';
    530     do {
    531         --ptr;
    532         assert(ptr >= buffer);
    533         *ptr = '0' + (value % 10);
    534         value /= 10;
    535     } while (value);
    536 
    537     _Py_write_noraise(fd, ptr, end - ptr);
    538 }
    539 
    540 /* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
    541    and write it into the file fd.
    542 
    543    This function is signal safe. */
    544 
    545 void
    546 _Py_DumpHexadecimal(int fd, unsigned long value, Py_ssize_t width)
    547 {
    548     char buffer[sizeof(unsigned long) * 2 + 1], *ptr, *end;
    549     const Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
    550 
    551     if (width > size)
    552         width = size;
    553     /* it's ok if width is negative */
    554 
    555     end = &buffer[size];
    556     ptr = end;
    557     *ptr = '\0';
    558     do {
    559         --ptr;
    560         assert(ptr >= buffer);
    561         *ptr = Py_hexdigits[value & 15];
    562         value >>= 4;
    563     } while ((end - ptr) < width || value);
    564 
    565     _Py_write_noraise(fd, ptr, end - ptr);
    566 }
    567 
    568 void
    569 _Py_DumpASCII(int fd, PyObject *text)
    570 {
    571     PyASCIIObject *ascii = (PyASCIIObject *)text;
    572     Py_ssize_t i, size;
    573     int truncated;
    574     int kind;
    575     void *data = NULL;
    576     wchar_t *wstr = NULL;
    577     Py_UCS4 ch;
    578 
    579     if (!PyUnicode_Check(text))
    580         return;
    581 
    582     size = ascii->length;
    583     kind = ascii->state.kind;
    584     if (kind == PyUnicode_WCHAR_KIND) {
    585         wstr = ((PyASCIIObject *)text)->wstr;
    586         if (wstr == NULL)
    587             return;
    588         size = ((PyCompactUnicodeObject *)text)->wstr_length;
    589     }
    590     else if (ascii->state.compact) {
    591         if (ascii->state.ascii)
    592             data = ((PyASCIIObject*)text) + 1;
    593         else
    594             data = ((PyCompactUnicodeObject*)text) + 1;
    595     }
    596     else {
    597         data = ((PyUnicodeObject *)text)->data.any;
    598         if (data == NULL)
    599             return;
    600     }
    601 
    602     if (MAX_STRING_LENGTH < size) {
    603         size = MAX_STRING_LENGTH;
    604         truncated = 1;
    605     }
    606     else {
    607         truncated = 0;
    608     }
    609 
    610     for (i=0; i < size; i++) {
    611         if (kind != PyUnicode_WCHAR_KIND)
    612             ch = PyUnicode_READ(kind, data, i);
    613         else
    614             ch = wstr[i];
    615         if (' ' <= ch && ch <= 126) {
    616             /* printable ASCII character */
    617             char c = (char)ch;
    618             _Py_write_noraise(fd, &c, 1);
    619         }
    620         else if (ch <= 0xff) {
    621             PUTS(fd, "\\x");
    622             _Py_DumpHexadecimal(fd, ch, 2);
    623         }
    624         else if (ch <= 0xffff) {
    625             PUTS(fd, "\\u");
    626             _Py_DumpHexadecimal(fd, ch, 4);
    627         }
    628         else {
    629             PUTS(fd, "\\U");
    630             _Py_DumpHexadecimal(fd, ch, 8);
    631         }
    632     }
    633     if (truncated) {
    634         PUTS(fd, "...");
    635     }
    636 }
    637 
    638 /* Write a frame into the file fd: "File "xxx", line xxx in xxx".
    639 
    640    This function is signal safe. */
    641 
    642 static void
    643 dump_frame(int fd, PyFrameObject *frame)
    644 {
    645     PyCodeObject *code;
    646     int lineno;
    647 
    648     code = frame->f_code;
    649     PUTS(fd, "  File ");
    650     if (code != NULL && code->co_filename != NULL
    651         && PyUnicode_Check(code->co_filename))
    652     {
    653         PUTS(fd, "\"");
    654         _Py_DumpASCII(fd, code->co_filename);
    655         PUTS(fd, "\"");
    656     } else {
    657         PUTS(fd, "???");
    658     }
    659 
    660     /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
    661     lineno = PyCode_Addr2Line(code, frame->f_lasti);
    662     PUTS(fd, ", line ");
    663     if (lineno >= 0) {
    664         _Py_DumpDecimal(fd, (unsigned long)lineno);
    665     }
    666     else {
    667         PUTS(fd, "???");
    668     }
    669     PUTS(fd, " in ");
    670 
    671     if (code != NULL && code->co_name != NULL
    672        && PyUnicode_Check(code->co_name)) {
    673         _Py_DumpASCII(fd, code->co_name);
    674     }
    675     else {
    676         PUTS(fd, "???");
    677     }
    678 
    679     PUTS(fd, "\n");
    680 }
    681 
    682 static void
    683 dump_traceback(int fd, PyThreadState *tstate, int write_header)
    684 {
    685     PyFrameObject *frame;
    686     unsigned int depth;
    687 
    688     if (write_header)
    689         PUTS(fd, "Stack (most recent call first):\n");
    690 
    691     frame = _PyThreadState_GetFrame(tstate);
    692     if (frame == NULL)
    693         return;
    694 
    695     depth = 0;
    696     while (frame != NULL) {
    697         if (MAX_FRAME_DEPTH <= depth) {
    698             PUTS(fd, "  ...\n");
    699             break;
    700         }
    701         if (!PyFrame_Check(frame))
    702             break;
    703         dump_frame(fd, frame);
    704         frame = frame->f_back;
    705         depth++;
    706     }
    707 }
    708 
    709 /* Dump the traceback of a Python thread into fd. Use write() to write the
    710    traceback and retry if write() is interrupted by a signal (failed with
    711    EINTR), but don't call the Python signal handler.
    712 
    713    The caller is responsible to call PyErr_CheckSignals() to call Python signal
    714    handlers if signals were received. */
    715 void
    716 _Py_DumpTraceback(int fd, PyThreadState *tstate)
    717 {
    718     dump_traceback(fd, tstate, 1);
    719 }
    720 
    721 /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
    722    is_current is true, "Thread 0xHHHH:\n" otherwise.
    723 
    724    This function is signal safe. */
    725 
    726 static void
    727 write_thread_id(int fd, PyThreadState *tstate, int is_current)
    728 {
    729     if (is_current)
    730         PUTS(fd, "Current thread 0x");
    731     else
    732         PUTS(fd, "Thread 0x");
    733     _Py_DumpHexadecimal(fd,
    734                         (unsigned long)tstate->thread_id,
    735                         sizeof(unsigned long) * 2);
    736     PUTS(fd, " (most recent call first):\n");
    737 }
    738 
    739 /* Dump the traceback of all Python threads into fd. Use write() to write the
    740    traceback and retry if write() is interrupted by a signal (failed with
    741    EINTR), but don't call the Python signal handler.
    742 
    743    The caller is responsible to call PyErr_CheckSignals() to call Python signal
    744    handlers if signals were received. */
    745 const char*
    746 _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
    747                          PyThreadState *current_tstate)
    748 {
    749     PyThreadState *tstate;
    750     unsigned int nthreads;
    751 
    752 #ifdef WITH_THREAD
    753     if (current_tstate == NULL) {
    754         /* _Py_DumpTracebackThreads() is called from signal handlers by
    755            faulthandler.
    756 
    757            SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
    758            and are thus delivered to the thread that caused the fault. Get the
    759            Python thread state of the current thread.
    760 
    761            PyThreadState_Get() doesn't give the state of the thread that caused
    762            the fault if the thread released the GIL, and so this function
    763            cannot be used. Read the thread local storage (TLS) instead: call
    764            PyGILState_GetThisThreadState(). */
    765         current_tstate = PyGILState_GetThisThreadState();
    766     }
    767 
    768     if (interp == NULL) {
    769         if (current_tstate == NULL) {
    770             interp = _PyGILState_GetInterpreterStateUnsafe();
    771             if (interp == NULL) {
    772                 /* We need the interpreter state to get Python threads */
    773                 return "unable to get the interpreter state";
    774             }
    775         }
    776         else {
    777             interp = current_tstate->interp;
    778         }
    779     }
    780 #else
    781     if (current_tstate == NULL) {
    782         /* Call _PyThreadState_UncheckedGet() instead of PyThreadState_Get()
    783            to not fail with a fatal error if the thread state is NULL. */
    784         current_tstate = _PyThreadState_UncheckedGet();
    785     }
    786 
    787     if (interp == NULL) {
    788         if (current_tstate == NULL) {
    789             /* We need the interpreter state to get Python threads */
    790             return "unable to get the interpreter state";
    791         }
    792         interp = current_tstate->interp;
    793     }
    794 #endif
    795     assert(interp != NULL);
    796 
    797     /* Get the current interpreter from the current thread */
    798     tstate = PyInterpreterState_ThreadHead(interp);
    799     if (tstate == NULL)
    800         return "unable to get the thread head state";
    801 
    802     /* Dump the traceback of each thread */
    803     tstate = PyInterpreterState_ThreadHead(interp);
    804     nthreads = 0;
    805     _Py_BEGIN_SUPPRESS_IPH
    806     do
    807     {
    808         if (nthreads != 0)
    809             PUTS(fd, "\n");
    810         if (nthreads >= MAX_NTHREADS) {
    811             PUTS(fd, "...\n");
    812             break;
    813         }
    814         write_thread_id(fd, tstate, tstate == current_tstate);
    815         dump_traceback(fd, tstate, 0);
    816         tstate = PyThreadState_Next(tstate);
    817         nthreads++;
    818     } while (tstate != NULL);
    819     _Py_END_SUPPRESS_IPH
    820 
    821     return NULL;
    822 }
    823 
    824