summaryrefslogtreecommitdiff
path: root/Python/traceback.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/traceback.c')
-rw-r--r--Python/traceback.c78
1 files changed, 62 insertions, 16 deletions
diff --git a/Python/traceback.c b/Python/traceback.c
index 74075c9481..7d1fc2e8ac 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, strlen(str))
+#define PUTS(fd, str) write(fd, str, (int)strlen(str))
#define MAX_STRING_LENGTH 500
#define MAX_FRAME_DEPTH 100
#define MAX_NTHREADS 100
@@ -21,6 +21,11 @@
/* Function from Parser/tokenizer.c */
extern char * PyTokenizer_FindEncodingFilename(int, PyObject *);
+_Py_IDENTIFIER(TextIOWrapper);
+_Py_IDENTIFIER(close);
+_Py_IDENTIFIER(open);
+_Py_IDENTIFIER(path);
+
static PyObject *
tb_dir(PyTracebackObject *self)
{
@@ -137,6 +142,39 @@ PyTraceBack_Here(PyFrameObject *frame)
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;
+
+ /* 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);
+
+ globals = PyDict_New();
+ if (!globals)
+ goto done;
+ code = PyCode_NewEmpty(filename, funcname, lineno);
+ if (!code)
+ goto done;
+ frame = PyFrame_New(PyThreadState_Get(), code, globals, NULL);
+ if (!frame)
+ goto done;
+ frame->f_lineno = lineno;
+
+ PyErr_Restore(exception, value, tb);
+ PyTraceBack_Here(frame);
+
+done:
+ Py_XDECREF(globals);
+ Py_XDECREF(code);
+ Py_XDECREF(frame);
+}
+
static PyObject *
_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
{
@@ -152,7 +190,6 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *
const char* filepath;
Py_ssize_t len;
PyObject* result;
- _Py_IDENTIFIER(open);
filebytes = PyUnicode_EncodeFSDefault(filename);
if (filebytes == NULL) {
@@ -169,7 +206,7 @@ _Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *
tail++;
taillen = strlen(tail);
- syspath = PySys_GetObject("path");
+ syspath = _PySys_GetObjectId(&PyId_path);
if (syspath == NULL || !PyList_Check(syspath))
goto error;
npath = PyList_Size(syspath);
@@ -232,9 +269,6 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
char buf[MAXPATHLEN+1];
int kind;
void *data;
- _Py_IDENTIFIER(close);
- _Py_IDENTIFIER(open);
- _Py_IDENTIFIER(TextIOWrapper);
/* open the file */
if (filename == NULL)
@@ -246,10 +280,12 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
binary = _PyObject_CallMethodId(io, &PyId_open, "Os", filename, "rb");
if (binary == NULL) {
+ PyErr_Clear();
+
binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
if (binary == NULL) {
Py_DECREF(io);
- return 0;
+ return -1;
}
}
@@ -261,6 +297,8 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
return 0;
}
found_encoding = PyTokenizer_FindEncodingFilename(fd, filename);
+ if (found_encoding == NULL)
+ PyErr_Clear();
encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
/* Reset position */
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
@@ -271,19 +309,27 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent)
}
fob = _PyObject_CallMethodId(io, &PyId_TextIOWrapper, "Os", binary, encoding);
Py_DECREF(io);
- Py_DECREF(binary);
PyMem_FREE(found_encoding);
if (fob == NULL) {
PyErr_Clear();
+
+ res = _PyObject_CallMethodId(binary, &PyId_close, "");
+ Py_DECREF(binary);
+ if (res)
+ Py_DECREF(res);
+ else
+ PyErr_Clear();
return 0;
}
+ Py_DECREF(binary);
/* get the line number lineno */
for (i = 0; i < lineno; i++) {
Py_XDECREF(lineobj);
lineobj = PyFile_GetLine(fob, -1);
if (!lineobj) {
+ PyErr_Clear();
err = -1;
break;
}
@@ -469,13 +515,13 @@ dump_decimal(int fd, int value)
write(fd, buffer, len);
}
-/* Format an integer in range [0; 0xffffffff] to hexdecimal of 'width' digits,
+/* Format an integer in range [0; 0xffffffff] to hexadecimal of 'width' digits,
and write it into the file fd.
This function is signal safe. */
static void
-dump_hexadecimal(int width, unsigned long value, int fd)
+dump_hexadecimal(int fd, unsigned long value, int width)
{
int len;
char buffer[sizeof(unsigned long) * 2 + 1];
@@ -542,15 +588,15 @@ dump_ascii(int fd, PyObject *text)
}
else if (ch < 0xff) {
PUTS(fd, "\\x");
- dump_hexadecimal(2, ch, fd);
+ dump_hexadecimal(fd, ch, 2);
}
else if (ch < 0xffff) {
PUTS(fd, "\\u");
- dump_hexadecimal(4, ch, fd);
+ dump_hexadecimal(fd, ch, 4);
}
else {
PUTS(fd, "\\U");
- dump_hexadecimal(8, ch, fd);
+ dump_hexadecimal(fd, ch, 8);
}
}
if (truncated)
@@ -601,7 +647,7 @@ dump_traceback(int fd, PyThreadState *tstate, int write_header)
unsigned int depth;
if (write_header)
- PUTS(fd, "Traceback (most recent call first):\n");
+ PUTS(fd, "Stack (most recent call first):\n");
frame = _PyThreadState_GetFrame(tstate);
if (frame == NULL)
@@ -639,8 +685,8 @@ write_thread_id(int fd, PyThreadState *tstate, int is_current)
PUTS(fd, "Current thread 0x");
else
PUTS(fd, "Thread 0x");
- dump_hexadecimal(sizeof(long)*2, (unsigned long)tstate->thread_id, fd);
- PUTS(fd, ":\n");
+ dump_hexadecimal(fd, (unsigned long)tstate->thread_id, sizeof(long)*2);
+ PUTS(fd, " (most recent call first):\n");
}
const char*