summaryrefslogtreecommitdiff
path: root/Python/traceback.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/traceback.c')
-rw-r--r--Python/traceback.c87
1 files changed, 54 insertions, 33 deletions
diff --git a/Python/traceback.c b/Python/traceback.c
index 7d1fc2e8ac..9e7fe3b5c6 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -13,7 +13,7 @@
#define OFF(x) offsetof(PyTracebackObject, x)
-#define PUTS(fd, str) write(fd, str, (int)strlen(str))
+#define PUTS(fd, str) _Py_write_noraise(fd, str, (int)strlen(str))
#define MAX_STRING_LENGTH 500
#define MAX_FRAME_DEPTH 100
#define MAX_NTHREADS 100
@@ -132,47 +132,53 @@ newtracebackobject(PyTracebackObject *next, PyFrameObject *frame)
int
PyTraceBack_Here(PyFrameObject *frame)
{
- PyThreadState *tstate = PyThreadState_GET();
- PyTracebackObject *oldtb = (PyTracebackObject *) tstate->curexc_traceback;
- PyTracebackObject *tb = newtracebackobject(oldtb, frame);
- if (tb == NULL)
+ PyObject *exc, *val, *tb, *newtb;
+ PyErr_Fetch(&exc, &val, &tb);
+ newtb = (PyObject *)newtracebackobject((PyTracebackObject *)tb, frame);
+ if (newtb == NULL) {
+ _PyErr_ChainExceptions(exc, val, tb);
return -1;
- tstate->curexc_traceback = (PyObject *)tb;
- Py_XDECREF(oldtb);
+ }
+ PyErr_Restore(exc, val, newtb);
+ Py_XDECREF(tb);
return 0;
}
/* Insert a frame into the traceback for (funcname, filename, lineno). */
void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
{
- PyObject *globals = NULL;
- PyCodeObject *code = NULL;
- PyFrameObject *frame = NULL;
- PyObject *exception, *value, *tb;
+ PyObject *globals;
+ PyCodeObject *code;
+ PyFrameObject *frame;
+ PyObject *exc, *val, *tb;
/* Save and clear the current exception. Python functions must not be
called with an exception set. Calling Python functions happens when
the codec of the filesystem encoding is implemented in pure Python. */
- PyErr_Fetch(&exception, &value, &tb);
+ PyErr_Fetch(&exc, &val, &tb);
globals = PyDict_New();
if (!globals)
- goto done;
+ goto error;
code = PyCode_NewEmpty(filename, funcname, lineno);
- if (!code)
- goto done;
+ if (!code) {
+ Py_DECREF(globals);
+ goto error;
+ }
frame = PyFrame_New(PyThreadState_Get(), code, globals, NULL);
+ Py_DECREF(globals);
+ Py_DECREF(code);
if (!frame)
- goto done;
+ goto error;
frame->f_lineno = lineno;
- PyErr_Restore(exception, value, tb);
+ PyErr_Restore(exc, val, tb);
PyTraceBack_Here(frame);
+ Py_DECREF(frame);
+ return;
-done:
- Py_XDECREF(globals);
- Py_XDECREF(code);
- Py_XDECREF(frame);
+error:
+ _PyErr_ChainExceptions(exc, val, tb);
}
static PyObject *
@@ -231,7 +237,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *
}
strcpy(namebuf, PyBytes_AS_STRING(path));
Py_DECREF(path);
- if (strlen(namebuf) != len)
+ if (strlen(namebuf) != (size_t)len)
continue; /* v contains '\0' */
if (len > 0 && namebuf[len-1] != SEP)
namebuf[len++] = SEP;
@@ -512,7 +518,7 @@ dump_decimal(int fd, int value)
len++;
} while (value);
reverse_string(buffer, len);
- write(fd, buffer, len);
+ _Py_write_noraise(fd, buffer, len);
}
/* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
@@ -532,7 +538,7 @@ dump_hexadecimal(int fd, unsigned long value, int width)
len++;
} while (len < width || value);
reverse_string(buffer, len);
- write(fd, buffer, len);
+ _Py_write_noraise(fd, buffer, len);
}
/* Write an unicode object into the file fd using ascii+backslashreplace.
@@ -582,15 +588,16 @@ dump_ascii(int fd, PyObject *text)
ch = PyUnicode_READ(kind, data, i);
else
ch = wstr[i];
- if (ch < 128) {
+ if (' ' <= ch && ch <= 126) {
+ /* printable ASCII character */
char c = (char)ch;
- write(fd, &c, 1);
+ _Py_write_noraise(fd, &c, 1);
}
- else if (ch < 0xff) {
+ else if (ch <= 0xff) {
PUTS(fd, "\\x");
dump_hexadecimal(fd, ch, 2);
}
- else if (ch < 0xffff) {
+ else if (ch <= 0xffff) {
PUTS(fd, "\\u");
dump_hexadecimal(fd, ch, 4);
}
@@ -618,9 +625,9 @@ dump_frame(int fd, PyFrameObject *frame)
if (code != NULL && code->co_filename != NULL
&& PyUnicode_Check(code->co_filename))
{
- write(fd, "\"", 1);
+ PUTS(fd, "\"");
dump_ascii(fd, code->co_filename);
- write(fd, "\"", 1);
+ PUTS(fd, "\"");
} else {
PUTS(fd, "???");
}
@@ -637,7 +644,7 @@ dump_frame(int fd, PyFrameObject *frame)
else
PUTS(fd, "???");
- write(fd, "\n", 1);
+ PUTS(fd, "\n");
}
static void
@@ -667,6 +674,12 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
}
}
+/* Dump the traceback of a Python thread into fd. Use write() to write the
+ traceback and retry if write() is interrupted by a signal (failed with
+ EINTR), but don't call the Python signal handler.
+
+ The caller is responsible to call PyErr_CheckSignals() to call Python signal
+ handlers if signals were received. */
void
_Py_DumpTraceback(int fd, PyThreadState *tstate)
{
@@ -685,10 +698,16 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
PUTS(fd, "Current thread 0x");
else
PUTS(fd, "Thread 0x");
- dump_hexadecimal(fd, (unsigned long)tstate->thread_id, sizeof(long)*2);
+ dump_hexadecimal(fd, (unsigned long)tstate->thread_id, sizeof(unsigned long)*2);
PUTS(fd, " (most recent call first):\n");
}
+/* Dump the traceback of all Python threads into fd. Use write() to write the
+ traceback and retry if write() is interrupted by a signal (failed with
+ EINTR), but don't call the Python signal handler.
+
+ The caller is responsible to call PyErr_CheckSignals() to call Python signal
+ handlers if signals were received. */
const char*
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
PyThreadState *current_thread)
@@ -704,10 +723,11 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
/* Dump the traceback of each thread */
tstate = PyInterpreterState_ThreadHead(interp);
nthreads = 0;
+ _Py_BEGIN_SUPPRESS_IPH
do
{
if (nthreads != 0)
- write(fd, "\n", 1);
+ PUTS(fd, "\n");
if (nthreads >= MAX_NTHREADS) {
PUTS(fd, "...\n");
break;
@@ -717,6 +737,7 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
tstate = PyThreadState_Next(tstate);
nthreads++;
} while (tstate != NULL);
+ _Py_END_SUPPRESS_IPH
return NULL;
}