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 /* Format an integer in range [0; 0xffffffff] to decimal and write it
626 into the file fd.
627
628 This function is signal safe. */
629
630 void
_Py_DumpDecimal(int fd,unsigned long value)631 _Py_DumpDecimal(int fd, unsigned long value)
632 {
633 /* maximum number of characters required for output of %lld or %p.
634 We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
635 plus 1 for the null byte. 53/22 is an upper bound for log10(256). */
636 char buffer[1 + (sizeof(unsigned long)*53-1) / 22 + 1];
637 char *ptr, *end;
638
639 end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
640 ptr = end;
641 *ptr = '\0';
642 do {
643 --ptr;
644 assert(ptr >= buffer);
645 *ptr = '0' + (value % 10);
646 value /= 10;
647 } while (value);
648
649 _Py_write_noraise(fd, ptr, end - ptr);
650 }
651
652 /* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
653 and write it into the file fd.
654
655 This function is signal safe. */
656
657 void
_Py_DumpHexadecimal(int fd,unsigned long value,Py_ssize_t width)658 _Py_DumpHexadecimal(int fd, unsigned long value, Py_ssize_t width)
659 {
660 char buffer[sizeof(unsigned long) * 2 + 1], *ptr, *end;
661 const Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
662
663 if (width > size)
664 width = size;
665 /* it's ok if width is negative */
666
667 end = &buffer[size];
668 ptr = end;
669 *ptr = '\0';
670 do {
671 --ptr;
672 assert(ptr >= buffer);
673 *ptr = Py_hexdigits[value & 15];
674 value >>= 4;
675 } while ((end - ptr) < width || value);
676
677 _Py_write_noraise(fd, ptr, end - ptr);
678 }
679
680 void
_Py_DumpASCII(int fd,PyObject * text)681 _Py_DumpASCII(int fd, PyObject *text)
682 {
683 PyASCIIObject *ascii = (PyASCIIObject *)text;
684 Py_ssize_t i, size;
685 int truncated;
686 int kind;
687 void *data = NULL;
688 wchar_t *wstr = NULL;
689 Py_UCS4 ch;
690
691 if (!PyUnicode_Check(text))
692 return;
693
694 size = ascii->length;
695 kind = ascii->state.kind;
696 if (kind == PyUnicode_WCHAR_KIND) {
697 wstr = ((PyASCIIObject *)text)->wstr;
698 if (wstr == NULL)
699 return;
700 size = ((PyCompactUnicodeObject *)text)->wstr_length;
701 }
702 else if (ascii->state.compact) {
703 if (ascii->state.ascii)
704 data = ((PyASCIIObject*)text) + 1;
705 else
706 data = ((PyCompactUnicodeObject*)text) + 1;
707 }
708 else {
709 data = ((PyUnicodeObject *)text)->data.any;
710 if (data == NULL)
711 return;
712 }
713
714 if (MAX_STRING_LENGTH < size) {
715 size = MAX_STRING_LENGTH;
716 truncated = 1;
717 }
718 else {
719 truncated = 0;
720 }
721
722 for (i=0; i < size; i++) {
723 if (kind != PyUnicode_WCHAR_KIND)
724 ch = PyUnicode_READ(kind, data, i);
725 else
726 ch = wstr[i];
727 if (' ' <= ch && ch <= 126) {
728 /* printable ASCII character */
729 char c = (char)ch;
730 _Py_write_noraise(fd, &c, 1);
731 }
732 else if (ch <= 0xff) {
733 PUTS(fd, "\\x");
734 _Py_DumpHexadecimal(fd, ch, 2);
735 }
736 else if (ch <= 0xffff) {
737 PUTS(fd, "\\u");
738 _Py_DumpHexadecimal(fd, ch, 4);
739 }
740 else {
741 PUTS(fd, "\\U");
742 _Py_DumpHexadecimal(fd, ch, 8);
743 }
744 }
745 if (truncated) {
746 PUTS(fd, "...");
747 }
748 }
749
750 /* Write a frame into the file fd: "File "xxx", line xxx in xxx".
751
752 This function is signal safe. */
753
754 static void
dump_frame(int fd,PyFrameObject * frame)755 dump_frame(int fd, PyFrameObject *frame)
756 {
757 PyCodeObject *code = PyFrame_GetCode(frame);
758 PUTS(fd, " File ");
759 if (code->co_filename != NULL
760 && PyUnicode_Check(code->co_filename))
761 {
762 PUTS(fd, "\"");
763 _Py_DumpASCII(fd, code->co_filename);
764 PUTS(fd, "\"");
765 } else {
766 PUTS(fd, "???");
767 }
768
769 /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
770 int lineno = PyCode_Addr2Line(code, frame->f_lasti);
771 PUTS(fd, ", line ");
772 if (lineno >= 0) {
773 _Py_DumpDecimal(fd, (unsigned long)lineno);
774 }
775 else {
776 PUTS(fd, "???");
777 }
778 PUTS(fd, " in ");
779
780 if (code->co_name != NULL
781 && PyUnicode_Check(code->co_name)) {
782 _Py_DumpASCII(fd, code->co_name);
783 }
784 else {
785 PUTS(fd, "???");
786 }
787
788 PUTS(fd, "\n");
789 Py_DECREF(code);
790 }
791
792 static void
dump_traceback(int fd,PyThreadState * tstate,int write_header)793 dump_traceback(int fd, PyThreadState *tstate, int write_header)
794 {
795 PyFrameObject *frame;
796 unsigned int depth;
797
798 if (write_header) {
799 PUTS(fd, "Stack (most recent call first):\n");
800 }
801
802 frame = PyThreadState_GetFrame(tstate);
803 if (frame == NULL) {
804 PUTS(fd, "<no Python frame>\n");
805 return;
806 }
807
808 depth = 0;
809 while (1) {
810 if (MAX_FRAME_DEPTH <= depth) {
811 Py_DECREF(frame);
812 PUTS(fd, " ...\n");
813 break;
814 }
815 if (!PyFrame_Check(frame)) {
816 Py_DECREF(frame);
817 break;
818 }
819 dump_frame(fd, frame);
820 PyFrameObject *back = PyFrame_GetBack(frame);
821 Py_DECREF(frame);
822
823 if (back == NULL) {
824 break;
825 }
826 frame = back;
827 depth++;
828 }
829 }
830
831 /* Dump the traceback of a Python thread into fd. Use write() to write the
832 traceback and retry if write() is interrupted by a signal (failed with
833 EINTR), but don't call the Python signal handler.
834
835 The caller is responsible to call PyErr_CheckSignals() to call Python signal
836 handlers if signals were received. */
837 void
_Py_DumpTraceback(int fd,PyThreadState * tstate)838 _Py_DumpTraceback(int fd, PyThreadState *tstate)
839 {
840 dump_traceback(fd, tstate, 1);
841 }
842
843 /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
844 is_current is true, "Thread 0xHHHH:\n" otherwise.
845
846 This function is signal safe. */
847
848 static void
write_thread_id(int fd,PyThreadState * tstate,int is_current)849 write_thread_id(int fd, PyThreadState *tstate, int is_current)
850 {
851 if (is_current)
852 PUTS(fd, "Current thread 0x");
853 else
854 PUTS(fd, "Thread 0x");
855 _Py_DumpHexadecimal(fd,
856 tstate->thread_id,
857 sizeof(unsigned long) * 2);
858 PUTS(fd, " (most recent call first):\n");
859 }
860
861 /* Dump the traceback of all Python threads into fd. Use write() to write the
862 traceback and retry if write() is interrupted by a signal (failed with
863 EINTR), but don't call the Python signal handler.
864
865 The caller is responsible to call PyErr_CheckSignals() to call Python signal
866 handlers if signals were received. */
867 const char*
_Py_DumpTracebackThreads(int fd,PyInterpreterState * interp,PyThreadState * current_tstate)868 _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
869 PyThreadState *current_tstate)
870 {
871 PyThreadState *tstate;
872 unsigned int nthreads;
873
874 if (current_tstate == NULL) {
875 /* _Py_DumpTracebackThreads() is called from signal handlers by
876 faulthandler.
877
878 SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
879 and are thus delivered to the thread that caused the fault. Get the
880 Python thread state of the current thread.
881
882 PyThreadState_Get() doesn't give the state of the thread that caused
883 the fault if the thread released the GIL, and so
884 _PyThreadState_GET() cannot be used. Read the thread specific
885 storage (TSS) instead: call PyGILState_GetThisThreadState(). */
886 current_tstate = PyGILState_GetThisThreadState();
887 }
888
889 if (interp == NULL) {
890 if (current_tstate == NULL) {
891 interp = _PyGILState_GetInterpreterStateUnsafe();
892 if (interp == NULL) {
893 /* We need the interpreter state to get Python threads */
894 return "unable to get the interpreter state";
895 }
896 }
897 else {
898 interp = current_tstate->interp;
899 }
900 }
901 assert(interp != NULL);
902
903 /* Get the current interpreter from the current thread */
904 tstate = PyInterpreterState_ThreadHead(interp);
905 if (tstate == NULL)
906 return "unable to get the thread head state";
907
908 /* Dump the traceback of each thread */
909 tstate = PyInterpreterState_ThreadHead(interp);
910 nthreads = 0;
911 _Py_BEGIN_SUPPRESS_IPH
912 do
913 {
914 if (nthreads != 0)
915 PUTS(fd, "\n");
916 if (nthreads >= MAX_NTHREADS) {
917 PUTS(fd, "...\n");
918 break;
919 }
920 write_thread_id(fd, tstate, tstate == current_tstate);
921 dump_traceback(fd, tstate, 0);
922 tstate = PyThreadState_Next(tstate);
923 nthreads++;
924 } while (tstate != NULL);
925 _Py_END_SUPPRESS_IPH
926
927 return NULL;
928 }
929
930