blob: 5d60dade4cb0803544bea8a100807bdd1513a291 [file] [log] [blame]
Guido van Rossumf70e43a1991-02-19 12:39:46 +00001
Guido van Rossum3f5da241990-12-20 15:06:42 +00002/* Traceback implementation */
3
Guido van Rossum65bf9f21997-04-29 18:33:38 +00004#include "Python.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +00005
Jeremy Hylton3e0055f2005-10-20 19:59:25 +00006#include "code.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +00007#include "frameobject.h"
Guido van Rossum3f5da241990-12-20 15:06:42 +00008#include "structmember.h"
Guido van Rossum7169dbb1992-02-26 15:17:59 +00009#include "osdefs.h"
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +000010#ifdef HAVE_FCNTL_H
11#include <fcntl.h>
12#endif
Guido van Rossum3f5da241990-12-20 15:06:42 +000013
Nicholas Bastina7604bf2004-03-21 18:37:23 +000014#define OFF(x) offsetof(PyTracebackObject, x)
Guido van Rossum3f5da241990-12-20 15:06:42 +000015
Victor Stinner84bb1cf2013-05-17 00:12:04 +020016#define PUTS(fd, str) write(fd, str, (int)strlen(str))
Victor Stinner54f939b2012-07-30 13:08:58 +020017#define MAX_STRING_LENGTH 500
Victor Stinner024e37a2011-03-31 01:31:06 +020018#define MAX_FRAME_DEPTH 100
19#define MAX_NTHREADS 100
20
Victor Stinnerfe7c5b52011-04-05 01:48:03 +020021/* Function from Parser/tokenizer.c */
22extern char * PyTokenizer_FindEncodingFilename(int, PyObject *);
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +000023
Victor Stinnerbd303c12013-11-07 23:07:29 +010024_Py_IDENTIFIER(TextIOWrapper);
25_Py_IDENTIFIER(close);
26_Py_IDENTIFIER(open);
27_Py_IDENTIFIER(path);
28
Collin Winter3eed7652007-08-14 17:53:54 +000029static PyObject *
30tb_dir(PyTracebackObject *self)
31{
32 return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
33 "tb_lasti", "tb_lineno");
34}
35
36static PyMethodDef tb_methods[] = {
37 {"__dir__", (PyCFunction)tb_dir, METH_NOARGS},
38 {NULL, NULL, 0, NULL},
39};
40
Neal Norwitz8dfc4a92007-08-11 06:39:53 +000041static PyMemberDef tb_memberlist[] = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000042 {"tb_next", T_OBJECT, OFF(tb_next), READONLY},
43 {"tb_frame", T_OBJECT, OFF(tb_frame), READONLY},
44 {"tb_lasti", T_INT, OFF(tb_lasti), READONLY},
45 {"tb_lineno", T_INT, OFF(tb_lineno), READONLY},
46 {NULL} /* Sentinel */
Guido van Rossum3f5da241990-12-20 15:06:42 +000047};
48
Guido van Rossum3f5da241990-12-20 15:06:42 +000049static void
Nicholas Bastina7604bf2004-03-21 18:37:23 +000050tb_dealloc(PyTracebackObject *tb)
Guido van Rossum3f5da241990-12-20 15:06:42 +000051{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000052 PyObject_GC_UnTrack(tb);
53 Py_TRASHCAN_SAFE_BEGIN(tb)
54 Py_XDECREF(tb->tb_next);
55 Py_XDECREF(tb->tb_frame);
56 PyObject_GC_Del(tb);
57 Py_TRASHCAN_SAFE_END(tb)
Guido van Rossum3f5da241990-12-20 15:06:42 +000058}
59
Jeremy Hyltonfd14d8e2001-10-22 22:17:41 +000060static int
Nicholas Bastina7604bf2004-03-21 18:37:23 +000061tb_traverse(PyTracebackObject *tb, visitproc visit, void *arg)
Jeremy Hyltonfd14d8e2001-10-22 22:17:41 +000062{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000063 Py_VISIT(tb->tb_next);
64 Py_VISIT(tb->tb_frame);
65 return 0;
Jeremy Hyltonfd14d8e2001-10-22 22:17:41 +000066}
67
68static void
Nicholas Bastina7604bf2004-03-21 18:37:23 +000069tb_clear(PyTracebackObject *tb)
Jeremy Hyltonfd14d8e2001-10-22 22:17:41 +000070{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000071 Py_CLEAR(tb->tb_next);
72 Py_CLEAR(tb->tb_frame);
Jeremy Hyltonfd14d8e2001-10-22 22:17:41 +000073}
74
Tim Petersd7c36522001-10-22 19:34:09 +000075PyTypeObject PyTraceBack_Type = {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +000076 PyVarObject_HEAD_INIT(&PyType_Type, 0)
77 "traceback",
78 sizeof(PyTracebackObject),
79 0,
80 (destructor)tb_dealloc, /*tp_dealloc*/
81 0, /*tp_print*/
82 0, /*tp_getattr*/
83 0, /*tp_setattr*/
84 0, /*tp_reserved*/
85 0, /*tp_repr*/
86 0, /*tp_as_number*/
87 0, /*tp_as_sequence*/
88 0, /*tp_as_mapping*/
89 0, /* tp_hash */
90 0, /* tp_call */
91 0, /* tp_str */
92 PyObject_GenericGetAttr, /* tp_getattro */
93 0, /* tp_setattro */
94 0, /* tp_as_buffer */
95 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
96 0, /* tp_doc */
97 (traverseproc)tb_traverse, /* tp_traverse */
98 (inquiry)tb_clear, /* tp_clear */
99 0, /* tp_richcompare */
100 0, /* tp_weaklistoffset */
101 0, /* tp_iter */
102 0, /* tp_iternext */
103 tb_methods, /* tp_methods */
104 tb_memberlist, /* tp_members */
105 0, /* tp_getset */
106 0, /* tp_base */
107 0, /* tp_dict */
Guido van Rossum3f5da241990-12-20 15:06:42 +0000108};
109
Nicholas Bastina7604bf2004-03-21 18:37:23 +0000110static PyTracebackObject *
111newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000112{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000113 PyTracebackObject *tb;
114 if ((next != NULL && !PyTraceBack_Check(next)) ||
115 frame == NULL || !PyFrame_Check(frame)) {
116 PyErr_BadInternalCall();
117 return NULL;
118 }
119 tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
120 if (tb != NULL) {
121 Py_XINCREF(next);
122 tb->tb_next = next;
123 Py_XINCREF(frame);
124 tb->tb_frame = frame;
125 tb->tb_lasti = frame->f_lasti;
126 tb->tb_lineno = PyFrame_GetLineNumber(frame);
127 PyObject_GC_Track(tb);
128 }
129 return tb;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000130}
131
Guido van Rossum3f5da241990-12-20 15:06:42 +0000132int
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000133PyTraceBack_Here(PyFrameObject *frame)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000134{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000135 PyThreadState *tstate = PyThreadState_GET();
136 PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
137 PyTracebackObject *tb = newtracebackobject(oldtb, frame);
138 if (tb == NULL)
139 return -1;
140 tstate->curexc_traceback = (PyObject *)tb;
141 Py_XDECREF(oldtb);
142 return 0;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000143}
144
Victor Stinner0fe25a42010-06-17 23:08:50 +0000145static PyObject *
146_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000147{
Victor Stinner0fe25a42010-06-17 23:08:50 +0000148 Py_ssize_t i;
149 PyObject *binary;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000150 PyObject *v;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000151 Py_ssize_t npath;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000152 size_t taillen;
153 PyObject *syspath;
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000154 PyObject *path;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000155 const char* tail;
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000156 PyObject *filebytes;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000157 const char* filepath;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000158 Py_ssize_t len;
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000159 PyObject* result;
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000160
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000161 filebytes = PyUnicode_EncodeFSDefault(filename);
162 if (filebytes == NULL) {
Victor Stinner0fe25a42010-06-17 23:08:50 +0000163 PyErr_Clear();
164 return NULL;
165 }
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000166 filepath = PyBytes_AS_STRING(filebytes);
Victor Stinner0fe25a42010-06-17 23:08:50 +0000167
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000168 /* Search tail of filename in sys.path before giving up */
Victor Stinner0fe25a42010-06-17 23:08:50 +0000169 tail = strrchr(filepath, SEP);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000170 if (tail == NULL)
Victor Stinner0fe25a42010-06-17 23:08:50 +0000171 tail = filepath;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000172 else
173 tail++;
174 taillen = strlen(tail);
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000175
Victor Stinnerbd303c12013-11-07 23:07:29 +0100176 syspath = _PySys_GetObjectId(&PyId_path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000177 if (syspath == NULL || !PyList_Check(syspath))
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000178 goto error;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000179 npath = PyList_Size(syspath);
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000180
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000181 for (i = 0; i < npath; i++) {
182 v = PyList_GetItem(syspath, i);
183 if (v == NULL) {
184 PyErr_Clear();
185 break;
186 }
187 if (!PyUnicode_Check(v))
188 continue;
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000189 path = PyUnicode_EncodeFSDefault(v);
Victor Stinner0fe25a42010-06-17 23:08:50 +0000190 if (path == NULL) {
191 PyErr_Clear();
192 continue;
193 }
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000194 len = PyBytes_GET_SIZE(path);
195 if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
196 Py_DECREF(path);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000197 continue; /* Too long */
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000198 }
199 strcpy(namebuf, PyBytes_AS_STRING(path));
200 Py_DECREF(path);
Victor Stinner98ea54c2014-08-15 23:30:40 +0200201 if (strlen(namebuf) != (size_t)len)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000202 continue; /* v contains '\0' */
203 if (len > 0 && namebuf[len-1] != SEP)
204 namebuf[len++] = SEP;
205 strcpy(namebuf+len, tail);
Victor Stinner0fe25a42010-06-17 23:08:50 +0000206
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200207 binary = _PyObject_CallMethodId(io, &PyId_open, "ss", namebuf, "rb");
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000208 if (binary != NULL) {
209 result = binary;
210 goto finally;
211 }
Victor Stinner0fe25a42010-06-17 23:08:50 +0000212 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000213 }
Victor Stinner4c7c8c32010-10-16 13:14:10 +0000214 goto error;
215
216error:
217 result = NULL;
218finally:
219 Py_DECREF(filebytes);
220 return result;
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000221}
222
Christian Heimes33fe8092008-04-13 13:53:33 +0000223int
Victor Stinner0fe25a42010-06-17 23:08:50 +0000224_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000225{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000226 int err = 0;
227 int fd;
228 int i;
229 char *found_encoding;
230 char *encoding;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000231 PyObject *io;
232 PyObject *binary;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000233 PyObject *fob = NULL;
234 PyObject *lineobj = NULL;
Antoine Pitroub86680e2010-10-14 21:15:17 +0000235 PyObject *res;
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000236 char buf[MAXPATHLEN+1];
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200237 int kind;
238 void *data;
Christian Heimes679db4a2008-01-18 09:56:22 +0000239
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000240 /* open the file */
241 if (filename == NULL)
242 return 0;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000243
244 io = PyImport_ImportModuleNoBlock("io");
245 if (io == NULL)
246 return -1;
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200247 binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb");
Victor Stinner0fe25a42010-06-17 23:08:50 +0000248
249 if (binary == NULL) {
Victor Stinnerceceaa02013-07-16 00:32:14 +0200250 PyErr_Clear();
251
Victor Stinner0fe25a42010-06-17 23:08:50 +0000252 binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
253 if (binary == NULL) {
254 Py_DECREF(io);
Victor Stinnerceceaa02013-07-16 00:32:14 +0200255 return -1;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000256 }
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000257 }
Christian Heimes33fe8092008-04-13 13:53:33 +0000258
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000259 /* use the right encoding to decode the file as unicode */
Victor Stinner0fe25a42010-06-17 23:08:50 +0000260 fd = PyObject_AsFileDescriptor(binary);
Christian Heimes8c077bc2013-07-21 01:53:10 +0200261 if (fd < 0) {
262 Py_DECREF(io);
263 Py_DECREF(binary);
Benjamin Peterson04b01dc2013-07-21 13:26:13 -0700264 return 0;
Christian Heimes8c077bc2013-07-21 01:53:10 +0200265 }
Victor Stinnerfe7c5b52011-04-05 01:48:03 +0200266 found_encoding = PyTokenizer_FindEncodingFilename(fd, filename);
Victor Stinner5272fa92013-12-19 13:39:32 +0100267 if (found_encoding == NULL)
268 PyErr_Clear();
Victor Stinner0fe25a42010-06-17 23:08:50 +0000269 encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
Christian Heimes1f347292013-07-21 02:12:35 +0200270 /* Reset position */
271 if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
272 Py_DECREF(io);
273 Py_DECREF(binary);
274 PyMem_FREE(found_encoding);
Benjamin Peterson04b01dc2013-07-21 13:26:13 -0700275 return 0;
Christian Heimes1f347292013-07-21 02:12:35 +0200276 }
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200277 fob = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "Os", binary, encoding);
Victor Stinner0fe25a42010-06-17 23:08:50 +0000278 Py_DECREF(io);
279 Py_DECREF(binary);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000280 PyMem_FREE(found_encoding);
Victor Stinner0fe25a42010-06-17 23:08:50 +0000281
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000282 if (fob == NULL) {
283 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000284 return 0;
285 }
Christian Heimes33fe8092008-04-13 13:53:33 +0000286
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000287 /* get the line number lineno */
288 for (i = 0; i < lineno; i++) {
289 Py_XDECREF(lineobj);
290 lineobj = PyFile_GetLine(fob, -1);
291 if (!lineobj) {
292 err = -1;
293 break;
294 }
295 }
Martin v. Löwisafe55bb2011-10-09 10:38:36 +0200296 res = _PyObject_CallMethodId(fob, &PyId_close, "");
Antoine Pitroub86680e2010-10-14 21:15:17 +0000297 if (res)
298 Py_DECREF(res);
299 else
300 PyErr_Clear();
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000301 Py_DECREF(fob);
302 if (!lineobj || !PyUnicode_Check(lineobj)) {
303 Py_XDECREF(lineobj);
304 return err;
305 }
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000306
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000307 /* remove the indentation of the line */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200308 kind = PyUnicode_KIND(lineobj);
309 data = PyUnicode_DATA(lineobj);
310 for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
311 Py_UCS4 ch = PyUnicode_READ(kind, data, i);
312 if (ch != ' ' && ch != '\t' && ch != '\014')
313 break;
314 }
315 if (i) {
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000316 PyObject *truncated;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200317 truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000318 if (truncated) {
319 Py_DECREF(lineobj);
320 lineobj = truncated;
321 } else {
322 PyErr_Clear();
323 }
324 }
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000325
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000326 /* Write some spaces before the line */
327 strcpy(buf, " ");
328 assert (strlen(buf) == 10);
329 while (indent > 0) {
Benjamin Peterson0f9b7d32013-07-21 13:29:37 -0700330 if (indent < 10)
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000331 buf[indent] = '\0';
332 err = PyFile_WriteString(buf, f);
333 if (err != 0)
334 break;
335 indent -= 10;
336 }
Amaury Forgeot d'Arccf8016a2008-10-09 23:37:48 +0000337
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000338 /* finally display the line */
339 if (err == 0)
340 err = PyFile_WriteObject(lineobj, f, Py_PRINT_RAW);
341 Py_DECREF(lineobj);
342 if (err == 0)
343 err = PyFile_WriteString("\n", f);
344 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000345}
346
Guido van Rossum7e8d26d1997-05-22 22:35:47 +0000347static int
Victor Stinner0fe25a42010-06-17 23:08:50 +0000348tb_displayline(PyObject *f, PyObject *filename, int lineno, PyObject *name)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000349{
Victor Stinner0fe25a42010-06-17 23:08:50 +0000350 int err;
351 PyObject *line;
Christian Heimes33fe8092008-04-13 13:53:33 +0000352
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000353 if (filename == NULL || name == NULL)
354 return -1;
Victor Stinner0fe25a42010-06-17 23:08:50 +0000355 line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
356 filename, lineno, name);
357 if (line == NULL)
358 return -1;
359 err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
360 Py_DECREF(line);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000361 if (err != 0)
362 return err;
Kristján Valur Jónssonc5963d32012-07-19 21:02:03 +0000363 /* ignore errors since we can't report them, can we? */
364 if (_Py_DisplaySourceLine(f, filename, lineno, 4))
365 PyErr_Clear();
366 return err;
Christian Heimes33fe8092008-04-13 13:53:33 +0000367}
368
369static int
370tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
371{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000372 int err = 0;
373 long depth = 0;
374 PyTracebackObject *tb1 = tb;
375 while (tb1 != NULL) {
376 depth++;
377 tb1 = tb1->tb_next;
378 }
379 while (tb != NULL && err == 0) {
380 if (depth <= limit) {
381 err = tb_displayline(f,
Victor Stinner0fe25a42010-06-17 23:08:50 +0000382 tb->tb_frame->f_code->co_filename,
383 tb->tb_lineno,
384 tb->tb_frame->f_code->co_name);
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000385 }
386 depth--;
387 tb = tb->tb_next;
388 if (err == 0)
389 err = PyErr_CheckSignals();
390 }
391 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000392}
393
Christian Heimes0fbab7f2007-12-04 21:55:18 +0000394#define PyTraceBack_LIMIT 1000
395
Guido van Rossum3f5da241990-12-20 15:06:42 +0000396int
Thomas Woutersf70ef4f2000-07-22 18:47:25 +0000397PyTraceBack_Print(PyObject *v, PyObject *f)
Guido van Rossum3f5da241990-12-20 15:06:42 +0000398{
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000399 int err;
400 PyObject *limitv;
401 long limit = PyTraceBack_LIMIT;
Christian Heimes0fbab7f2007-12-04 21:55:18 +0000402
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000403 if (v == NULL)
404 return 0;
405 if (!PyTraceBack_Check(v)) {
406 PyErr_BadInternalCall();
407 return -1;
408 }
409 limitv = PySys_GetObject("tracebacklimit");
410 if (limitv) {
411 PyObject *exc_type, *exc_value, *exc_tb;
Christian Heimes0fbab7f2007-12-04 21:55:18 +0000412
Antoine Pitrouf95a1b32010-05-09 15:52:27 +0000413 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
414 limit = PyLong_AsLong(limitv);
415 if (limit == -1 && PyErr_Occurred()) {
416 if (PyErr_ExceptionMatches(PyExc_OverflowError)) {
417 limit = PyTraceBack_LIMIT;
418 }
419 else {
420 Py_XDECREF(exc_type);
421 Py_XDECREF(exc_value);
422 Py_XDECREF(exc_tb);
423 return 0;
424 }
425 }
426 else if (limit <= 0) {
427 limit = PyTraceBack_LIMIT;
428 }
429 PyErr_Restore(exc_type, exc_value, exc_tb);
430 }
431 err = PyFile_WriteString("Traceback (most recent call last):\n", f);
432 if (!err)
433 err = tb_printinternal((PyTracebackObject *)v, f, limit);
434 return err;
Guido van Rossum3f5da241990-12-20 15:06:42 +0000435}
Victor Stinner024e37a2011-03-31 01:31:06 +0200436
437/* Reverse a string. For example, "abcd" becomes "dcba".
438
439 This function is signal safe. */
440
441static void
442reverse_string(char *text, const size_t len)
443{
444 char tmp;
445 size_t i, j;
446 if (len == 0)
447 return;
448 for (i=0, j=len-1; i < j; i++, j--) {
449 tmp = text[i];
450 text[i] = text[j];
451 text[j] = tmp;
452 }
453}
454
455/* Format an integer in range [0; 999999] to decimal,
456 and write it into the file fd.
457
458 This function is signal safe. */
459
460static void
461dump_decimal(int fd, int value)
462{
463 char buffer[7];
464 int len;
465 if (value < 0 || 999999 < value)
466 return;
467 len = 0;
468 do {
469 buffer[len] = '0' + (value % 10);
470 value /= 10;
471 len++;
472 } while (value);
473 reverse_string(buffer, len);
474 write(fd, buffer, len);
475}
476
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700477/* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
Victor Stinner024e37a2011-03-31 01:31:06 +0200478 and write it into the file fd.
479
480 This function is signal safe. */
481
482static void
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700483dump_hexadecimal(int fd, unsigned long value, int width)
Victor Stinner024e37a2011-03-31 01:31:06 +0200484{
Victor Stinner024e37a2011-03-31 01:31:06 +0200485 int len;
486 char buffer[sizeof(unsigned long) * 2 + 1];
487 len = 0;
488 do {
Victor Stinnerf5cff562011-10-14 02:13:11 +0200489 buffer[len] = Py_hexdigits[value & 15];
Victor Stinner024e37a2011-03-31 01:31:06 +0200490 value >>= 4;
491 len++;
492 } while (len < width || value);
493 reverse_string(buffer, len);
494 write(fd, buffer, len);
495}
496
497/* Write an unicode object into the file fd using ascii+backslashreplace.
498
499 This function is signal safe. */
500
501static void
502dump_ascii(int fd, PyObject *text)
503{
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200504 PyASCIIObject *ascii = (PyASCIIObject *)text;
Victor Stinner024e37a2011-03-31 01:31:06 +0200505 Py_ssize_t i, size;
506 int truncated;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200507 int kind;
Victor Stinnera336de72011-10-05 22:44:12 +0200508 void *data = NULL;
509 wchar_t *wstr = NULL;
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200510 Py_UCS4 ch;
Victor Stinner024e37a2011-03-31 01:31:06 +0200511
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200512 size = ascii->length;
513 kind = ascii->state.kind;
514 if (ascii->state.compact) {
515 if (ascii->state.ascii)
516 data = ((PyASCIIObject*)text) + 1;
517 else
518 data = ((PyCompactUnicodeObject*)text) + 1;
519 }
Victor Stinnera336de72011-10-05 22:44:12 +0200520 else if (kind != PyUnicode_WCHAR_KIND) {
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200521 data = ((PyUnicodeObject *)text)->data.any;
522 if (data == NULL)
523 return;
524 }
Victor Stinnera336de72011-10-05 22:44:12 +0200525 else {
526 wstr = ((PyASCIIObject *)text)->wstr;
527 if (wstr == NULL)
528 return;
529 size = ((PyCompactUnicodeObject *)text)->wstr_length;
530 }
Victor Stinner024e37a2011-03-31 01:31:06 +0200531
532 if (MAX_STRING_LENGTH < size) {
533 size = MAX_STRING_LENGTH;
534 truncated = 1;
535 }
536 else
537 truncated = 0;
538
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200539 for (i=0; i < size; i++) {
Victor Stinnera336de72011-10-05 22:44:12 +0200540 if (kind != PyUnicode_WCHAR_KIND)
541 ch = PyUnicode_READ(kind, data, i);
542 else
543 ch = wstr[i];
Victor Stinnerb86f08f2014-10-03 14:18:09 +0200544 if (' ' <= ch && ch <= 126) {
545 /* printable ASCII character */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200546 char c = (char)ch;
Victor Stinner024e37a2011-03-31 01:31:06 +0200547 write(fd, &c, 1);
548 }
Victor Stinnerb86f08f2014-10-03 14:18:09 +0200549 else if (ch <= 0xff) {
Victor Stinner024e37a2011-03-31 01:31:06 +0200550 PUTS(fd, "\\x");
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700551 dump_hexadecimal(fd, ch, 2);
Victor Stinner024e37a2011-03-31 01:31:06 +0200552 }
Victor Stinnerb86f08f2014-10-03 14:18:09 +0200553 else if (ch <= 0xffff) {
Victor Stinner024e37a2011-03-31 01:31:06 +0200554 PUTS(fd, "\\u");
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700555 dump_hexadecimal(fd, ch, 4);
Victor Stinner024e37a2011-03-31 01:31:06 +0200556 }
557 else {
558 PUTS(fd, "\\U");
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700559 dump_hexadecimal(fd, ch, 8);
Victor Stinner024e37a2011-03-31 01:31:06 +0200560 }
561 }
562 if (truncated)
563 PUTS(fd, "...");
564}
565
566/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
567
568 This function is signal safe. */
569
570static void
571dump_frame(int fd, PyFrameObject *frame)
572{
573 PyCodeObject *code;
574 int lineno;
575
576 code = frame->f_code;
577 PUTS(fd, " File ");
578 if (code != NULL && code->co_filename != NULL
579 && PyUnicode_Check(code->co_filename))
580 {
581 write(fd, "\"", 1);
582 dump_ascii(fd, code->co_filename);
583 write(fd, "\"", 1);
584 } else {
585 PUTS(fd, "???");
586 }
587
588 /* PyFrame_GetLineNumber() was introduced in Python 2.7.0 and 3.2.0 */
Martin v. Löwisd63a3b82011-09-28 07:41:54 +0200589 lineno = PyCode_Addr2Line(code, frame->f_lasti);
Victor Stinner024e37a2011-03-31 01:31:06 +0200590 PUTS(fd, ", line ");
591 dump_decimal(fd, lineno);
592 PUTS(fd, " in ");
593
594 if (code != NULL && code->co_name != NULL
595 && PyUnicode_Check(code->co_name))
596 dump_ascii(fd, code->co_name);
597 else
598 PUTS(fd, "???");
599
600 write(fd, "\n", 1);
601}
602
Victor Stinnerfcb88c42011-04-01 15:34:01 +0200603static void
Victor Stinner024e37a2011-03-31 01:31:06 +0200604dump_traceback(int fd, PyThreadState *tstate, int write_header)
605{
606 PyFrameObject *frame;
607 unsigned int depth;
608
Victor Stinner024e37a2011-03-31 01:31:06 +0200609 if (write_header)
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700610 PUTS(fd, "Stack (most recent call first):\n");
Victor Stinnerfcb88c42011-04-01 15:34:01 +0200611
612 frame = _PyThreadState_GetFrame(tstate);
613 if (frame == NULL)
614 return;
615
Victor Stinner024e37a2011-03-31 01:31:06 +0200616 depth = 0;
617 while (frame != NULL) {
618 if (MAX_FRAME_DEPTH <= depth) {
619 PUTS(fd, " ...\n");
620 break;
621 }
622 if (!PyFrame_Check(frame))
623 break;
624 dump_frame(fd, frame);
625 frame = frame->f_back;
626 depth++;
627 }
Victor Stinner024e37a2011-03-31 01:31:06 +0200628}
629
Victor Stinnerfcb88c42011-04-01 15:34:01 +0200630void
Victor Stinner024e37a2011-03-31 01:31:06 +0200631_Py_DumpTraceback(int fd, PyThreadState *tstate)
632{
Victor Stinnerfcb88c42011-04-01 15:34:01 +0200633 dump_traceback(fd, tstate, 1);
Victor Stinner024e37a2011-03-31 01:31:06 +0200634}
635
636/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
637 is_current is true, "Thread 0xHHHH:\n" otherwise.
638
639 This function is signal safe. */
640
641static void
642write_thread_id(int fd, PyThreadState *tstate, int is_current)
643{
644 if (is_current)
645 PUTS(fd, "Current thread 0x");
646 else
647 PUTS(fd, "Thread 0x");
Victor Stinnerb86f08f2014-10-03 14:18:09 +0200648 dump_hexadecimal(fd, (unsigned long)tstate->thread_id, sizeof(unsigned long)*2);
Guido van Rossum7be5d7d2013-10-20 18:21:02 -0700649 PUTS(fd, " (most recent call first):\n");
Victor Stinner024e37a2011-03-31 01:31:06 +0200650}
651
652const char*
653_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
654 PyThreadState *current_thread)
655{
656 PyThreadState *tstate;
657 unsigned int nthreads;
658
659 /* Get the current interpreter from the current thread */
660 tstate = PyInterpreterState_ThreadHead(interp);
661 if (tstate == NULL)
662 return "unable to get the thread head state";
663
664 /* Dump the traceback of each thread */
665 tstate = PyInterpreterState_ThreadHead(interp);
666 nthreads = 0;
667 do
668 {
669 if (nthreads != 0)
670 write(fd, "\n", 1);
671 if (nthreads >= MAX_NTHREADS) {
672 PUTS(fd, "...\n");
673 break;
674 }
675 write_thread_id(fd, tstate, tstate == current_thread);
676 dump_traceback(fd, tstate, 0);
677 tstate = PyThreadState_Next(tstate);
678 nthreads++;
679 } while (tstate != NULL);
680
681 return NULL;
682}
683