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