1
2 /* Traceback implementation */
3
4 #include "Python.h"
5 #include "pycore_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,PyObject * Py_UNUSED (ignored))90 tb_dir(PyTracebackObject *self, PyObject *Py_UNUSED(ignored))
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_BEGIN(tb, tb_dealloc)
167 Py_XDECREF(tb->tb_next);
168 Py_XDECREF(tb->tb_frame);
169 PyObject_GC_Del(tb);
170 Py_TRASHCAN_END
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_vectorcall_offset*/
196 0, /*tp_getattr*/
197 0, /*tp_setattr*/
198 0, /*tp_as_async*/
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
231 PyObject*
_PyTraceBack_FromFrame(PyObject * tb_next,PyFrameObject * frame)232 _PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
233 {
234 assert(tb_next == NULL || PyTraceBack_Check(tb_next));
235 assert(frame != NULL);
236
237 return tb_create_raw((PyTracebackObject *)tb_next, frame, frame->f_lasti,
238 PyFrame_GetLineNumber(frame));
239 }
240
241
242 int
PyTraceBack_Here(PyFrameObject * frame)243 PyTraceBack_Here(PyFrameObject *frame)
244 {
245 PyObject *exc, *val, *tb, *newtb;
246 PyErr_Fetch(&exc, &val, &tb);
247 newtb = _PyTraceBack_FromFrame(tb, frame);
248 if (newtb == NULL) {
249 _PyErr_ChainExceptions(exc, val, tb);
250 return -1;
251 }
252 PyErr_Restore(exc, val, newtb);
253 Py_XDECREF(tb);
254 return 0;
255 }
256
257 /* Insert a frame into the traceback for (funcname, filename, lineno). */
_PyTraceback_Add(const char * funcname,const char * filename,int lineno)258 void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
259 {
260 PyObject *globals;
261 PyCodeObject *code;
262 PyFrameObject *frame;
263 PyObject *exc, *val, *tb;
264
265 /* Save and clear the current exception. Python functions must not be
266 called with an exception set. Calling Python functions happens when
267 the codec of the filesystem encoding is implemented in pure Python. */
268 PyErr_Fetch(&exc, &val, &tb);
269
270 globals = PyDict_New();
271 if (!globals)
272 goto error;
273 code = PyCode_NewEmpty(filename, funcname, lineno);
274 if (!code) {
275 Py_DECREF(globals);
276 goto error;
277 }
278 frame = PyFrame_New(PyThreadState_Get(), code, globals, NULL);
279 Py_DECREF(globals);
280 Py_DECREF(code);
281 if (!frame)
282 goto error;
283 frame->f_lineno = lineno;
284
285 PyErr_Restore(exc, val, tb);
286 PyTraceBack_Here(frame);
287 Py_DECREF(frame);
288 return;
289
290 error:
291 _PyErr_ChainExceptions(exc, val, tb);
292 }
293
294 static PyObject *
_Py_FindSourceFile(PyObject * filename,char * namebuf,size_t namelen,PyObject * io)295 _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
296 {
297 Py_ssize_t i;
298 PyObject *binary;
299 PyObject *v;
300 Py_ssize_t npath;
301 size_t taillen;
302 PyObject *syspath;
303 PyObject *path;
304 const char* tail;
305 PyObject *filebytes;
306 const char* filepath;
307 Py_ssize_t len;
308 PyObject* result;
309
310 filebytes = PyUnicode_EncodeFSDefault(filename);
311 if (filebytes == NULL) {
312 PyErr_Clear();
313 return NULL;
314 }
315 filepath = PyBytes_AS_STRING(filebytes);
316
317 /* Search tail of filename in sys.path before giving up */
318 tail = strrchr(filepath, SEP);
319 if (tail == NULL)
320 tail = filepath;
321 else
322 tail++;
323 taillen = strlen(tail);
324
325 syspath = _PySys_GetObjectId(&PyId_path);
326 if (syspath == NULL || !PyList_Check(syspath))
327 goto error;
328 npath = PyList_Size(syspath);
329
330 for (i = 0; i < npath; i++) {
331 v = PyList_GetItem(syspath, i);
332 if (v == NULL) {
333 PyErr_Clear();
334 break;
335 }
336 if (!PyUnicode_Check(v))
337 continue;
338 path = PyUnicode_EncodeFSDefault(v);
339 if (path == NULL) {
340 PyErr_Clear();
341 continue;
342 }
343 len = PyBytes_GET_SIZE(path);
344 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
345 Py_DECREF(path);
346 continue; /* Too long */
347 }
348 strcpy(namebuf, PyBytes_AS_STRING(path));
349 Py_DECREF(path);
350 if (strlen(namebuf) != (size_t)len)
351 continue; /* v contains '\0' */
352 if (len > 0 && namebuf[len-1] != SEP)
353 namebuf[len++] = SEP;
354 strcpy(namebuf+len, tail);
355
356 binary = _PyObject_CallMethodId(io, &PyId_open, "ss", namebuf, "rb");
357 if (binary != NULL) {
358 result = binary;
359 goto finally;
360 }
361 PyErr_Clear();
362 }
363 goto error;
364
365 error:
366 result = NULL;
367 finally:
368 Py_DECREF(filebytes);
369 return result;
370 }
371
372 int
_Py_DisplaySourceLine(PyObject * f,PyObject * filename,int lineno,int indent)373 _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
374 {
375 int err = 0;
376 int fd;
377 int i;
378 char *found_encoding;
379 char *encoding;
380 PyObject *io;
381 PyObject *binary;
382 PyObject *fob = NULL;
383 PyObject *lineobj = NULL;
384 PyObject *res;
385 char buf[MAXPATHLEN+1];
386 int kind;
387 void *data;
388
389 /* open the file */
390 if (filename == NULL)
391 return 0;
392
393 io = PyImport_ImportModuleNoBlock("io");
394 if (io == NULL)
395 return -1;
396 binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb");
397
398 if (binary == NULL) {
399 PyErr_Clear();
400
401 binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
402 if (binary == NULL) {
403 Py_DECREF(io);
404 return -1;
405 }
406 }
407
408 /* use the right encoding to decode the file as unicode */
409 fd = PyObject_AsFileDescriptor(binary);
410 if (fd < 0) {
411 Py_DECREF(io);
412 Py_DECREF(binary);
413 return 0;
414 }
415 found_encoding = PyTokenizer_FindEncodingFilename(fd, filename);
416 if (found_encoding == NULL)
417 PyErr_Clear();
418 encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
419 /* Reset position */
420 if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
421 Py_DECREF(io);
422 Py_DECREF(binary);
423 PyMem_FREE(found_encoding);
424 return 0;
425 }
426 fob = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "Os", binary, encoding);
427 Py_DECREF(io);
428 PyMem_FREE(found_encoding);
429
430 if (fob == NULL) {
431 PyErr_Clear();
432
433 res = _PyObject_CallMethodId(binary, &PyId_close, NULL);
434 Py_DECREF(binary);
435 if (res)
436 Py_DECREF(res);
437 else
438 PyErr_Clear();
439 return 0;
440 }
441 Py_DECREF(binary);
442
443 /* get the line number lineno */
444 for (i = 0; i < lineno; i++) {
445 Py_XDECREF(lineobj);
446 lineobj = PyFile_GetLine(fob, -1);
447 if (!lineobj) {
448 PyErr_Clear();
449 err = -1;
450 break;
451 }
452 }
453 res = _PyObject_CallMethodId(fob, &PyId_close, NULL);
454 if (res)
455 Py_DECREF(res);
456 else
457 PyErr_Clear();
458 Py_DECREF(fob);
459 if (!lineobj || !PyUnicode_Check(lineobj)) {
460 Py_XDECREF(lineobj);
461 return err;
462 }
463
464 /* remove the indentation of the line */
465 kind = PyUnicode_KIND(lineobj);
466 data = PyUnicode_DATA(lineobj);
467 for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
468 Py_UCS4 ch = PyUnicode_READ(kind, data, i);
469 if (ch != ' ' && ch != '\t' && ch != '\014')
470 break;
471 }
472 if (i) {
473 PyObject *truncated;
474 truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
475 if (truncated) {
476 Py_DECREF(lineobj);
477 lineobj = truncated;
478 } else {
479 PyErr_Clear();
480 }
481 }
482
483 /* Write some spaces before the line */
484 strcpy(buf, " ");
485 assert (strlen(buf) == 10);
486 while (indent > 0) {
487 if (indent < 10)
488 buf[indent] = '\0';
489 err = PyFile_WriteString(buf, f);
490 if (err != 0)
491 break;
492 indent -= 10;
493 }
494
495 /* finally display the line */
496 if (err == 0)
497 err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW);
498 Py_DECREF(lineobj);
499 if (err == 0)
500 err = PyFile_WriteString("\n", f);
501 return err;
502 }
503
504 static int
tb_displayline(PyObject * f,PyObject * filename,int lineno,PyObject * name)505 tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name)
506 {
507 int err;
508 PyObject *line;
509
510 if (filename == NULL || name == NULL)
511 return -1;
512 line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
513 filename, lineno, name);
514 if (line == NULL)
515 return -1;
516 err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
517 Py_DECREF(line);
518 if (err != 0)
519 return err;
520 /* ignore errors since we can't report them, can we? */
521 if (_Py_DisplaySourceLine(f, filename, lineno, 4))
522 PyErr_Clear();
523 return err;
524 }
525
526 static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
527
528 static int
tb_print_line_repeated(PyObject * f,long cnt)529 tb_print_line_repeated(PyObject *f, long cnt)
530 {
531 cnt -= TB_RECURSIVE_CUTOFF;
532 PyObject *line = PyUnicode_FromFormat(
533 (cnt > 1)
534 ? " [Previous line repeated %ld more times]\n"
535 : " [Previous line repeated %ld more time]\n",
536 cnt);
537 if (line == NULL) {
538 return -1;
539 }
540 int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
541 Py_DECREF(line);
542 return err;
543 }
544
545 static int
tb_printinternal(PyTracebackObject * tb,PyObject * f,long limit)546 tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
547 {
548 int err = 0;
549 Py_ssize_t depth = 0;
550 PyObject *last_file = NULL;
551 int last_line = -1;
552 PyObject *last_name = NULL;
553 long cnt = 0;
554 PyTracebackObject *tb1 = tb;
555 while (tb1 != NULL) {
556 depth++;
557 tb1 = tb1->tb_next;
558 }
559 while (tb != NULL && depth > limit) {
560 depth--;
561 tb = tb->tb_next;
562 }
563 while (tb != NULL && err == 0) {
564 if (last_file == NULL ||
565 tb->tb_frame->f_code->co_filename != last_file ||
566 last_line == -1 || tb->tb_lineno != last_line ||
567 last_name == NULL || tb->tb_frame->f_code->co_name != last_name) {
568 if (cnt > TB_RECURSIVE_CUTOFF) {
569 err = tb_print_line_repeated(f, cnt);
570 }
571 last_file = tb->tb_frame->f_code->co_filename;
572 last_line = tb->tb_lineno;
573 last_name = tb->tb_frame->f_code->co_name;
574 cnt = 0;
575 }
576 cnt++;
577 if (err == 0 && cnt <= TB_RECURSIVE_CUTOFF) {
578 err = tb_displayline(f,
579 tb->tb_frame->f_code->co_filename,
580 tb->tb_lineno,
581 tb->tb_frame->f_code->co_name);
582 if (err == 0) {
583 err = PyErr_CheckSignals();
584 }
585 }
586 tb = tb->tb_next;
587 }
588 if (err == 0 && cnt > TB_RECURSIVE_CUTOFF) {
589 err = tb_print_line_repeated(f, cnt);
590 }
591 return err;
592 }
593
594 #define PyTraceBack_LIMIT 1000
595
596 int
PyTraceBack_Print(PyObject * v,PyObject * f)597 PyTraceBack_Print(PyObject *v, PyObject *f)
598 {
599 int err;
600 PyObject *limitv;
601 long limit = PyTraceBack_LIMIT;
602
603 if (v == NULL)
604 return 0;
605 if (!PyTraceBack_Check(v)) {
606 PyErr_BadInternalCall();
607 return -1;
608 }
609 limitv = PySys_GetObject("tracebacklimit");
610 if (limitv && PyLong_Check(limitv)) {
611 int overflow;
612 limit = PyLong_AsLongAndOverflow(limitv, &overflow);
613 if (overflow > 0) {
614 limit = LONG_MAX;
615 }
616 else if (limit <= 0) {
617 return 0;
618 }
619 }
620 err = PyFile_WriteString("Traceback (most recent call last):\n", f);
621 if (!err)
622 err = tb_printinternal((PyTracebackObject *)v, f, limit);
623 return err;
624 }
625
626 /* Reverse a string. For example, "abcd" becomes "dcba".
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;
758 int lineno;
759
760 code = frame->f_code;
761 PUTS(fd, " File ");
762 if (code != NULL && code->co_filename != NULL
763 && PyUnicode_Check(code->co_filename))
764 {
765 PUTS(fd, "\"");
766 _Py_DumpASCII(fd, code->co_filename);
767 PUTS(fd, "\"");
768 } else {
769 PUTS(fd, "???");
770 }
771
772 /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
773 lineno = PyCode_Addr2Line(code, frame->f_lasti);
774 PUTS(fd, ", line ");
775 if (lineno >= 0) {
776 _Py_DumpDecimal(fd, (unsigned long)lineno);
777 }
778 else {
779 PUTS(fd, "???");
780 }
781 PUTS(fd, " in ");
782
783 if (code != NULL && code->co_name != NULL
784 && PyUnicode_Check(code->co_name)) {
785 _Py_DumpASCII(fd, code->co_name);
786 }
787 else {
788 PUTS(fd, "???");
789 }
790
791 PUTS(fd, "\n");
792 }
793
794 static void
dump_traceback(int fd,PyThreadState * tstate,int write_header)795 dump_traceback(int fd, PyThreadState *tstate, int write_header)
796 {
797 PyFrameObject *frame;
798 unsigned int depth;
799
800 if (write_header) {
801 PUTS(fd, "Stack (most recent call first):\n");
802 }
803
804 frame = _PyThreadState_GetFrame(tstate);
805 if (frame == NULL) {
806 PUTS(fd, "<no Python frame>\n");
807 return;
808 }
809
810 depth = 0;
811 while (frame != NULL) {
812 if (MAX_FRAME_DEPTH <= depth) {
813 PUTS(fd, " ...\n");
814 break;
815 }
816 if (!PyFrame_Check(frame))
817 break;
818 dump_frame(fd, frame);
819 frame = frame->f_back;
820 depth++;
821 }
822 }
823
824 /* Dump the traceback of a Python thread into fd. Use write() to write the
825 traceback and retry if write() is interrupted by a signal (failed with
826 EINTR), but don't call the Python signal handler.
827
828 The caller is responsible to call PyErr_CheckSignals() to call Python signal
829 handlers if signals were received. */
830 void
_Py_DumpTraceback(int fd,PyThreadState * tstate)831 _Py_DumpTraceback(int fd, PyThreadState *tstate)
832 {
833 dump_traceback(fd, tstate, 1);
834 }
835
836 /* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
837 is_current is true, "Thread 0xHHHH:\n" otherwise.
838
839 This function is signal safe. */
840
841 static void
write_thread_id(int fd,PyThreadState * tstate,int is_current)842 write_thread_id(int fd, PyThreadState *tstate, int is_current)
843 {
844 if (is_current)
845 PUTS(fd, "Current thread 0x");
846 else
847 PUTS(fd, "Thread 0x");
848 _Py_DumpHexadecimal(fd,
849 tstate->thread_id,
850 sizeof(unsigned long) * 2);
851 PUTS(fd, " (most recent call first):\n");
852 }
853
854 /* Dump the traceback of all Python threads into fd. Use write() to write the
855 traceback and retry if write() is interrupted by a signal (failed with
856 EINTR), but don't call the Python signal handler.
857
858 The caller is responsible to call PyErr_CheckSignals() to call Python signal
859 handlers if signals were received. */
860 const char*
_Py_DumpTracebackThreads(int fd,PyInterpreterState * interp,PyThreadState * current_tstate)861 _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
862 PyThreadState *current_tstate)
863 {
864 PyThreadState *tstate;
865 unsigned int nthreads;
866
867 if (current_tstate == NULL) {
868 /* _Py_DumpTracebackThreads() is called from signal handlers by
869 faulthandler.
870
871 SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
872 and are thus delivered to the thread that caused the fault. Get the
873 Python thread state of the current thread.
874
875 PyThreadState_Get() doesn't give the state of the thread that caused
876 the fault if the thread released the GIL, and so
877 _PyThreadState_GET() cannot be used. Read the thread specific
878 storage (TSS) instead: call PyGILState_GetThisThreadState(). */
879 current_tstate = PyGILState_GetThisThreadState();
880 }
881
882 if (interp == NULL) {
883 if (current_tstate == NULL) {
884 interp = _PyGILState_GetInterpreterStateUnsafe();
885 if (interp == NULL) {
886 /* We need the interpreter state to get Python threads */
887 return "unable to get the interpreter state";
888 }
889 }
890 else {
891 interp = current_tstate->interp;
892 }
893 }
894 assert(interp != NULL);
895
896 /* Get the current interpreter from the current thread */
897 tstate = PyInterpreterState_ThreadHead(interp);
898 if (tstate == NULL)
899 return "unable to get the thread head state";
900
901 /* Dump the traceback of each thread */
902 tstate = PyInterpreterState_ThreadHead(interp);
903 nthreads = 0;
904 _Py_BEGIN_SUPPRESS_IPH
905 do
906 {
907 if (nthreads != 0)
908 PUTS(fd, "\n");
909 if (nthreads >= MAX_NTHREADS) {
910 PUTS(fd, "...\n");
911 break;
912 }
913 write_thread_id(fd, tstate, tstate == current_tstate);
914 dump_traceback(fd, tstate, 0);
915 tstate = PyThreadState_Next(tstate);
916 nthreads++;
917 } while (tstate != NULL);
918 _Py_END_SUPPRESS_IPH
919
920 return NULL;
921 }
922
923