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