1991-02-19 12:39:46 +00:00
|
|
|
|
1990-12-20 15:06:42 +00:00
|
|
|
/* Traceback implementation */
|
|
|
|
|
1997-04-29 18:33:38 +00:00
|
|
|
#include "Python.h"
|
2022-02-08 13:39:07 -07:00
|
|
|
#include "pycore_call.h" // _PyObject_CallMethodFormat()
|
2021-10-13 15:03:35 +02:00
|
|
|
#include "pycore_fileutils.h" // _Py_BEGIN_SUPPRESS_IPH
|
2025-03-20 12:35:23 +01:00
|
|
|
#include "pycore_frame.h" // PyFrameObject
|
2021-10-13 15:03:35 +02:00
|
|
|
#include "pycore_interp.h" // PyInterpreterState.gc
|
2025-03-20 12:35:23 +01:00
|
|
|
#include "pycore_interpframe.h" // _PyFrame_GetCode()
|
2023-03-16 19:03:52 +00:00
|
|
|
#include "pycore_pyerrors.h" // _PyErr_GetRaisedException()
|
2021-10-13 14:09:13 +02:00
|
|
|
#include "pycore_pystate.h" // _PyThreadState_GET()
|
2021-11-05 09:39:18 +00:00
|
|
|
#include "pycore_traceback.h" // EXCEPTION_TB_HEADER
|
2022-06-19 12:02:33 +02:00
|
|
|
|
|
|
|
#include "frameobject.h" // PyFrame_New()
|
2023-07-25 15:28:30 +02:00
|
|
|
|
2020-04-15 03:24:57 +02:00
|
|
|
#include "osdefs.h" // SEP
|
2023-09-30 22:06:45 +02:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
# include <unistd.h> // lseek()
|
2008-10-09 23:37:48 +00:00
|
|
|
#endif
|
2025-04-23 18:23:24 +01:00
|
|
|
|
|
|
|
#if (defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H) && defined(HAVE_LINK_H))
|
|
|
|
# define _PY_HAS_BACKTRACE_HEADERS 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if (defined(__APPLE__) && defined(HAVE_EXECINFO_H) && defined(HAVE_DLFCN_H))
|
|
|
|
# define _PY_HAS_BACKTRACE_HEADERS 1
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _PY_HAS_BACKTRACE_HEADERS
|
2025-04-21 15:48:02 -04:00
|
|
|
# include <execinfo.h> // backtrace(), backtrace_symbols()
|
|
|
|
# include <dlfcn.h> // dladdr1()
|
2025-04-23 18:23:24 +01:00
|
|
|
#ifdef HAVE_LINK_H
|
|
|
|
# include <link.h> // struct DL_info
|
|
|
|
#endif
|
2025-04-28 11:55:02 +02:00
|
|
|
# if defined(__APPLE__) && defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR)
|
2025-04-23 18:23:24 +01:00
|
|
|
# define CAN_C_BACKTRACE
|
2025-04-28 11:55:02 +02:00
|
|
|
# elif defined(HAVE_BACKTRACE) && defined(HAVE_DLADDR1)
|
2025-04-21 15:48:02 -04:00
|
|
|
# define CAN_C_BACKTRACE
|
|
|
|
# endif
|
|
|
|
#endif
|
1990-12-20 15:06:42 +00:00
|
|
|
|
2025-04-21 15:48:02 -04:00
|
|
|
#if defined(__STDC_NO_VLA__) && (__STDC_NO_VLA__ == 1)
|
|
|
|
/* Use alloca() for VLAs. */
|
|
|
|
# define VLA(type, name, size) type *name = alloca(size)
|
|
|
|
#elif !defined(__STDC_NO_VLA__) || (__STDC_NO_VLA__ == 0)
|
|
|
|
/* Use actual C VLAs.*/
|
|
|
|
# define VLA(type, name, size) type name[size]
|
|
|
|
#elif defined(CAN_C_BACKTRACE)
|
|
|
|
/* VLAs are not possible. Disable C stack trace functions. */
|
|
|
|
# undef CAN_C_BACKTRACE
|
|
|
|
#endif
|
1990-12-20 15:06:42 +00:00
|
|
|
|
2023-09-30 22:06:45 +02:00
|
|
|
#define OFF(x) offsetof(PyTracebackObject, x)
|
2025-04-04 14:24:41 +02:00
|
|
|
#define PUTS(fd, str) (void)_Py_write_noraise(fd, str, strlen(str))
|
2023-09-30 22:06:45 +02:00
|
|
|
|
2012-07-30 13:08:58 +02:00
|
|
|
#define MAX_STRING_LENGTH 500
|
2011-03-31 01:31:06 +02:00
|
|
|
#define MAX_FRAME_DEPTH 100
|
|
|
|
#define MAX_NTHREADS 100
|
|
|
|
|
2023-10-12 09:34:35 +02:00
|
|
|
/* Function from Parser/tokenizer/file_tokenizer.c */
|
2021-10-13 17:22:14 +02:00
|
|
|
extern char* _PyTokenizer_FindEncodingFilename(int, PyObject *);
|
2008-10-09 23:37:48 +00:00
|
|
|
|
2018-01-07 05:30:18 -08:00
|
|
|
/*[clinic input]
|
2024-04-12 13:56:41 +03:00
|
|
|
class traceback "PyTracebackObject *" "&PyTraceback_Type"
|
2018-01-07 05:30:18 -08:00
|
|
|
[clinic start generated code]*/
|
2024-04-12 13:56:41 +03:00
|
|
|
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=cf96294b2bebc811]*/
|
2018-01-07 05:30:18 -08:00
|
|
|
|
2025-01-27 15:07:39 +01:00
|
|
|
#define _PyTracebackObject_CAST(op) ((PyTracebackObject *)(op))
|
|
|
|
|
2018-01-07 05:30:18 -08:00
|
|
|
#include "clinic/traceback.c.h"
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
tb_create_raw(PyTracebackObject *next, PyFrameObject *frame, int lasti,
|
|
|
|
int lineno)
|
|
|
|
{
|
|
|
|
PyTracebackObject *tb;
|
|
|
|
if ((next != NULL && !PyTraceBack_Check(next)) ||
|
|
|
|
frame == NULL || !PyFrame_Check(frame)) {
|
|
|
|
PyErr_BadInternalCall();
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
tb = PyObject_GC_New(PyTracebackObject, &PyTraceBack_Type);
|
|
|
|
if (tb != NULL) {
|
2022-11-10 11:23:36 +01:00
|
|
|
tb->tb_next = (PyTracebackObject*)Py_XNewRef(next);
|
|
|
|
tb->tb_frame = (PyFrameObject*)Py_XNewRef(frame);
|
2018-01-07 05:30:18 -08:00
|
|
|
tb->tb_lasti = lasti;
|
|
|
|
tb->tb_lineno = lineno;
|
|
|
|
PyObject_GC_Track(tb);
|
|
|
|
}
|
|
|
|
return (PyObject *)tb;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*[clinic input]
|
|
|
|
@classmethod
|
2024-04-12 13:56:41 +03:00
|
|
|
traceback.__new__ as tb_new
|
2018-01-07 05:30:18 -08:00
|
|
|
|
|
|
|
tb_next: object
|
|
|
|
tb_frame: object(type='PyFrameObject *', subclass_of='&PyFrame_Type')
|
|
|
|
tb_lasti: int
|
|
|
|
tb_lineno: int
|
|
|
|
|
|
|
|
Create a new traceback object.
|
|
|
|
[clinic start generated code]*/
|
|
|
|
|
|
|
|
static PyObject *
|
|
|
|
tb_new_impl(PyTypeObject *type, PyObject *tb_next, PyFrameObject *tb_frame,
|
|
|
|
int tb_lasti, int tb_lineno)
|
2024-04-12 13:56:41 +03:00
|
|
|
/*[clinic end generated code: output=fa077debd72d861a input=b88143145454cb59]*/
|
2018-01-07 05:30:18 -08:00
|
|
|
{
|
|
|
|
if (tb_next == Py_None) {
|
|
|
|
tb_next = NULL;
|
|
|
|
} else if (!PyTraceBack_Check(tb_next)) {
|
|
|
|
return PyErr_Format(PyExc_TypeError,
|
|
|
|
"expected traceback object or None, got '%s'",
|
|
|
|
Py_TYPE(tb_next)->tp_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
return tb_create_raw((PyTracebackObject *)tb_next, tb_frame, tb_lasti,
|
|
|
|
tb_lineno);
|
|
|
|
}
|
|
|
|
|
2007-08-14 17:53:54 +00:00
|
|
|
static PyObject *
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_dir(PyObject *Py_UNUSED(self), PyObject *Py_UNUSED(ignored))
|
2007-08-14 17:53:54 +00:00
|
|
|
{
|
|
|
|
return Py_BuildValue("[ssss]", "tb_frame", "tb_next",
|
|
|
|
"tb_lasti", "tb_lineno");
|
|
|
|
}
|
|
|
|
|
2025-03-20 12:03:54 +05:30
|
|
|
/*[clinic input]
|
|
|
|
@critical_section
|
|
|
|
@getter
|
|
|
|
traceback.tb_next
|
|
|
|
[clinic start generated code]*/
|
|
|
|
|
2018-01-07 05:30:18 -08:00
|
|
|
static PyObject *
|
2025-03-20 12:03:54 +05:30
|
|
|
traceback_tb_next_get_impl(PyTracebackObject *self)
|
|
|
|
/*[clinic end generated code: output=963634df7d5fc837 input=8f6345f2b73cb965]*/
|
2018-01-07 05:30:18 -08:00
|
|
|
{
|
|
|
|
PyObject* ret = (PyObject*)self->tb_next;
|
|
|
|
if (!ret) {
|
|
|
|
ret = Py_None;
|
|
|
|
}
|
2022-11-10 11:23:36 +01:00
|
|
|
return Py_NewRef(ret);
|
2018-01-07 05:30:18 -08:00
|
|
|
}
|
|
|
|
|
2023-10-31 15:02:31 +00:00
|
|
|
static int
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_get_lineno(PyObject *op)
|
|
|
|
{
|
|
|
|
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
|
2023-10-31 15:02:31 +00:00
|
|
|
_PyInterpreterFrame* frame = tb->tb_frame->f_frame;
|
|
|
|
assert(frame != NULL);
|
|
|
|
return PyCode_Addr2Line(_PyFrame_GetCode(frame), tb->tb_lasti);
|
|
|
|
}
|
|
|
|
|
|
|
|
static PyObject *
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_lineno_get(PyObject *op, void *Py_UNUSED(_))
|
2023-10-31 15:02:31 +00:00
|
|
|
{
|
2025-01-27 15:07:39 +01:00
|
|
|
PyTracebackObject *self = _PyTracebackObject_CAST(op);
|
2023-10-31 15:02:31 +00:00
|
|
|
int lineno = self->tb_lineno;
|
|
|
|
if (lineno == -1) {
|
2025-01-27 15:07:39 +01:00
|
|
|
lineno = tb_get_lineno(op);
|
2023-10-31 15:02:31 +00:00
|
|
|
if (lineno < 0) {
|
|
|
|
Py_RETURN_NONE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return PyLong_FromLong(lineno);
|
|
|
|
}
|
|
|
|
|
2025-03-20 12:03:54 +05:30
|
|
|
/*[clinic input]
|
|
|
|
@critical_section
|
|
|
|
@setter
|
|
|
|
traceback.tb_next
|
|
|
|
[clinic start generated code]*/
|
|
|
|
|
2018-01-07 05:30:18 -08:00
|
|
|
static int
|
2025-03-20 12:03:54 +05:30
|
|
|
traceback_tb_next_set_impl(PyTracebackObject *self, PyObject *value)
|
|
|
|
/*[clinic end generated code: output=d4868cbc48f2adac input=ce66367f85e3c443]*/
|
2018-01-07 05:30:18 -08:00
|
|
|
{
|
2025-03-20 12:03:54 +05:30
|
|
|
if (!value) {
|
2018-01-07 05:30:18 -08:00
|
|
|
PyErr_Format(PyExc_TypeError, "can't delete tb_next attribute");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We accept None or a traceback object, and map None -> NULL (inverse of
|
|
|
|
tb_next_get) */
|
2025-03-20 12:03:54 +05:30
|
|
|
if (value == Py_None) {
|
|
|
|
value = NULL;
|
|
|
|
} else if (!PyTraceBack_Check(value)) {
|
2018-01-07 05:30:18 -08:00
|
|
|
PyErr_Format(PyExc_TypeError,
|
|
|
|
"expected traceback object, got '%s'",
|
2025-03-20 12:03:54 +05:30
|
|
|
Py_TYPE(value)->tp_name);
|
2018-01-07 05:30:18 -08:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Check for loops */
|
2025-03-20 12:03:54 +05:30
|
|
|
PyTracebackObject *cursor = (PyTracebackObject *)value;
|
|
|
|
Py_XINCREF(cursor);
|
2018-01-07 05:30:18 -08:00
|
|
|
while (cursor) {
|
|
|
|
if (cursor == self) {
|
|
|
|
PyErr_Format(PyExc_ValueError, "traceback loop detected");
|
2025-03-20 12:03:54 +05:30
|
|
|
Py_DECREF(cursor);
|
2018-01-07 05:30:18 -08:00
|
|
|
return -1;
|
|
|
|
}
|
2025-03-20 12:03:54 +05:30
|
|
|
Py_BEGIN_CRITICAL_SECTION(cursor);
|
|
|
|
Py_XINCREF(cursor->tb_next);
|
|
|
|
Py_SETREF(cursor, cursor->tb_next);
|
|
|
|
Py_END_CRITICAL_SECTION();
|
2018-01-07 05:30:18 -08:00
|
|
|
}
|
|
|
|
|
2025-03-20 12:03:54 +05:30
|
|
|
Py_XSETREF(self->tb_next, (PyTracebackObject *)Py_XNewRef(value));
|
2018-01-07 05:30:18 -08:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-08-14 17:53:54 +00:00
|
|
|
static PyMethodDef tb_methods[] = {
|
2025-01-27 15:07:39 +01:00
|
|
|
{"__dir__", tb_dir, METH_NOARGS, NULL},
|
2007-08-14 17:53:54 +00:00
|
|
|
{NULL, NULL, 0, NULL},
|
|
|
|
};
|
|
|
|
|
2007-08-11 06:39:53 +00:00
|
|
|
static PyMemberDef tb_memberlist[] = {
|
2023-07-25 15:28:30 +02:00
|
|
|
{"tb_frame", _Py_T_OBJECT, OFF(tb_frame), Py_READONLY|Py_AUDIT_READ},
|
|
|
|
{"tb_lasti", Py_T_INT, OFF(tb_lasti), Py_READONLY},
|
2010-05-09 15:52:27 +00:00
|
|
|
{NULL} /* Sentinel */
|
1990-12-20 15:06:42 +00:00
|
|
|
};
|
|
|
|
|
2018-01-07 05:30:18 -08:00
|
|
|
static PyGetSetDef tb_getsetters[] = {
|
2025-03-20 12:03:54 +05:30
|
|
|
TRACEBACK_TB_NEXT_GETSETDEF
|
2025-01-27 15:07:39 +01:00
|
|
|
{"tb_lineno", tb_lineno_get, NULL, NULL, NULL},
|
2018-01-07 05:30:18 -08:00
|
|
|
{NULL} /* Sentinel */
|
|
|
|
};
|
|
|
|
|
1990-12-20 15:06:42 +00:00
|
|
|
static void
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_dealloc(PyObject *op)
|
1990-12-20 15:06:42 +00:00
|
|
|
{
|
2025-01-27 15:07:39 +01:00
|
|
|
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
|
2010-05-09 15:52:27 +00:00
|
|
|
PyObject_GC_UnTrack(tb);
|
|
|
|
Py_XDECREF(tb->tb_next);
|
|
|
|
Py_XDECREF(tb->tb_frame);
|
|
|
|
PyObject_GC_Del(tb);
|
1990-12-20 15:06:42 +00:00
|
|
|
}
|
|
|
|
|
2001-10-22 22:17:41 +00:00
|
|
|
static int
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_traverse(PyObject *op, visitproc visit, void *arg)
|
2001-10-22 22:17:41 +00:00
|
|
|
{
|
2025-01-27 15:07:39 +01:00
|
|
|
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
|
2010-05-09 15:52:27 +00:00
|
|
|
Py_VISIT(tb->tb_next);
|
|
|
|
Py_VISIT(tb->tb_frame);
|
|
|
|
return 0;
|
2001-10-22 22:17:41 +00:00
|
|
|
}
|
|
|
|
|
2018-11-27 19:34:35 +02:00
|
|
|
static int
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_clear(PyObject *op)
|
2001-10-22 22:17:41 +00:00
|
|
|
{
|
2025-01-27 15:07:39 +01:00
|
|
|
PyTracebackObject *tb = _PyTracebackObject_CAST(op);
|
2010-05-09 15:52:27 +00:00
|
|
|
Py_CLEAR(tb->tb_next);
|
|
|
|
Py_CLEAR(tb->tb_frame);
|
2018-11-27 19:34:35 +02:00
|
|
|
return 0;
|
2001-10-22 22:17:41 +00:00
|
|
|
}
|
|
|
|
|
2001-10-22 19:34:09 +00:00
|
|
|
PyTypeObject PyTraceBack_Type = {
|
2010-05-09 15:52:27 +00:00
|
|
|
PyVarObject_HEAD_INIT(&PyType_Type, 0)
|
|
|
|
"traceback",
|
|
|
|
sizeof(PyTracebackObject),
|
|
|
|
0,
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_dealloc, /*tp_dealloc*/
|
2019-05-31 04:13:39 +02:00
|
|
|
0, /*tp_vectorcall_offset*/
|
2010-05-09 15:52:27 +00:00
|
|
|
0, /*tp_getattr*/
|
|
|
|
0, /*tp_setattr*/
|
2019-05-31 04:13:39 +02:00
|
|
|
0, /*tp_as_async*/
|
2010-05-09 15:52:27 +00:00
|
|
|
0, /*tp_repr*/
|
|
|
|
0, /*tp_as_number*/
|
|
|
|
0, /*tp_as_sequence*/
|
|
|
|
0, /*tp_as_mapping*/
|
|
|
|
0, /* tp_hash */
|
|
|
|
0, /* tp_call */
|
|
|
|
0, /* tp_str */
|
|
|
|
PyObject_GenericGetAttr, /* tp_getattro */
|
|
|
|
0, /* tp_setattro */
|
|
|
|
0, /* tp_as_buffer */
|
|
|
|
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,/* tp_flags */
|
2018-01-07 05:30:18 -08:00
|
|
|
tb_new__doc__, /* tp_doc */
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_traverse, /* tp_traverse */
|
|
|
|
tb_clear, /* tp_clear */
|
2010-05-09 15:52:27 +00:00
|
|
|
0, /* tp_richcompare */
|
|
|
|
0, /* tp_weaklistoffset */
|
|
|
|
0, /* tp_iter */
|
|
|
|
0, /* tp_iternext */
|
|
|
|
tb_methods, /* tp_methods */
|
|
|
|
tb_memberlist, /* tp_members */
|
2018-01-07 05:30:18 -08:00
|
|
|
tb_getsetters, /* tp_getset */
|
2010-05-09 15:52:27 +00:00
|
|
|
0, /* tp_base */
|
|
|
|
0, /* tp_dict */
|
2018-01-07 05:30:18 -08:00
|
|
|
0, /* tp_descr_get */
|
|
|
|
0, /* tp_descr_set */
|
|
|
|
0, /* tp_dictoffset */
|
|
|
|
0, /* tp_init */
|
|
|
|
0, /* tp_alloc */
|
|
|
|
tb_new, /* tp_new */
|
1990-12-20 15:06:42 +00:00
|
|
|
};
|
|
|
|
|
2019-05-23 01:00:58 +02:00
|
|
|
|
|
|
|
PyObject*
|
|
|
|
_PyTraceBack_FromFrame(PyObject *tb_next, PyFrameObject *frame)
|
|
|
|
{
|
|
|
|
assert(tb_next == NULL || PyTraceBack_Check(tb_next));
|
|
|
|
assert(frame != NULL);
|
2022-04-07 12:31:01 -07:00
|
|
|
int addr = _PyInterpreterFrame_LASTI(frame->f_frame) * sizeof(_Py_CODEUNIT);
|
2023-10-31 15:02:31 +00:00
|
|
|
return tb_create_raw((PyTracebackObject *)tb_next, frame, addr, -1);
|
2019-05-23 01:00:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1990-12-20 15:06:42 +00:00
|
|
|
int
|
2000-07-22 18:47:25 +00:00
|
|
|
PyTraceBack_Here(PyFrameObject *frame)
|
1990-12-20 15:06:42 +00:00
|
|
|
{
|
2023-03-16 19:03:52 +00:00
|
|
|
PyObject *exc = PyErr_GetRaisedException();
|
|
|
|
assert(PyExceptionInstance_Check(exc));
|
|
|
|
PyObject *tb = PyException_GetTraceback(exc);
|
|
|
|
PyObject *newtb = _PyTraceBack_FromFrame(tb, frame);
|
|
|
|
Py_XDECREF(tb);
|
2016-10-18 13:23:18 +03:00
|
|
|
if (newtb == NULL) {
|
2023-03-16 19:03:52 +00:00
|
|
|
_PyErr_ChainExceptions1(exc);
|
2010-05-09 15:52:27 +00:00
|
|
|
return -1;
|
2016-10-18 13:23:18 +03:00
|
|
|
}
|
2023-03-16 19:03:52 +00:00
|
|
|
PyException_SetTraceback(exc, newtb);
|
|
|
|
Py_XDECREF(newtb);
|
|
|
|
PyErr_SetRaisedException(exc);
|
2010-05-09 15:52:27 +00:00
|
|
|
return 0;
|
1990-12-20 15:06:42 +00:00
|
|
|
}
|
|
|
|
|
2014-10-08 20:00:09 +02:00
|
|
|
/* Insert a frame into the traceback for (funcname, filename, lineno). */
|
2015-06-21 15:59:46 +03:00
|
|
|
void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
|
2014-10-08 20:00:09 +02:00
|
|
|
{
|
2016-10-18 13:23:18 +03:00
|
|
|
PyObject *globals;
|
|
|
|
PyCodeObject *code;
|
|
|
|
PyFrameObject *frame;
|
2021-10-13 14:09:13 +02:00
|
|
|
PyThreadState *tstate = _PyThreadState_GET();
|
2014-10-08 20:00:09 +02:00
|
|
|
|
|
|
|
/* 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. */
|
2023-02-08 09:31:12 +00:00
|
|
|
PyObject *exc = _PyErr_GetRaisedException(tstate);
|
2014-10-08 20:00:09 +02:00
|
|
|
|
|
|
|
globals = PyDict_New();
|
|
|
|
if (!globals)
|
2016-10-18 13:23:18 +03:00
|
|
|
goto error;
|
2014-10-08 20:00:09 +02:00
|
|
|
code = PyCode_NewEmpty(filename, funcname, lineno);
|
2016-10-18 13:23:18 +03:00
|
|
|
if (!code) {
|
|
|
|
Py_DECREF(globals);
|
|
|
|
goto error;
|
|
|
|
}
|
2021-10-13 14:09:13 +02:00
|
|
|
frame = PyFrame_New(tstate, code, globals, NULL);
|
2016-10-18 13:23:18 +03:00
|
|
|
Py_DECREF(globals);
|
|
|
|
Py_DECREF(code);
|
2014-10-08 20:00:09 +02:00
|
|
|
if (!frame)
|
2016-10-18 13:23:18 +03:00
|
|
|
goto error;
|
2014-10-08 20:00:09 +02:00
|
|
|
frame->f_lineno = lineno;
|
|
|
|
|
2023-02-08 09:31:12 +00:00
|
|
|
_PyErr_SetRaisedException(tstate, exc);
|
2014-10-08 20:00:09 +02:00
|
|
|
PyTraceBack_Here(frame);
|
2016-10-18 13:23:18 +03:00
|
|
|
Py_DECREF(frame);
|
|
|
|
return;
|
2014-10-08 20:00:09 +02:00
|
|
|
|
2016-10-18 13:23:18 +03:00
|
|
|
error:
|
2023-02-08 09:31:12 +00:00
|
|
|
_PyErr_ChainExceptions1(exc);
|
2014-10-08 20:00:09 +02:00
|
|
|
}
|
|
|
|
|
2010-06-17 23:08:50 +00:00
|
|
|
static PyObject *
|
|
|
|
_Py_FindSourceFile(PyObject *filename, char* namebuf, size_t namelen, PyObject *io)
|
2008-10-09 23:37:48 +00:00
|
|
|
{
|
2010-06-17 23:08:50 +00:00
|
|
|
Py_ssize_t i;
|
|
|
|
PyObject *binary;
|
2010-05-09 15:52:27 +00:00
|
|
|
PyObject *v;
|
2010-06-17 23:08:50 +00:00
|
|
|
Py_ssize_t npath;
|
2010-05-09 15:52:27 +00:00
|
|
|
size_t taillen;
|
|
|
|
PyObject *syspath;
|
2010-10-16 13:14:10 +00:00
|
|
|
PyObject *path;
|
2010-05-09 15:52:27 +00:00
|
|
|
const char* tail;
|
2010-10-16 13:14:10 +00:00
|
|
|
PyObject *filebytes;
|
2010-06-17 23:08:50 +00:00
|
|
|
const char* filepath;
|
2010-05-09 15:52:27 +00:00
|
|
|
Py_ssize_t len;
|
2010-10-16 13:14:10 +00:00
|
|
|
PyObject* result;
|
2022-02-08 13:39:07 -07:00
|
|
|
PyObject *open = NULL;
|
2010-05-09 15:52:27 +00:00
|
|
|
|
2010-10-16 13:14:10 +00:00
|
|
|
filebytes = PyUnicode_EncodeFSDefault(filename);
|
|
|
|
if (filebytes == NULL) {
|
2010-06-17 23:08:50 +00:00
|
|
|
PyErr_Clear();
|
|
|
|
return NULL;
|
|
|
|
}
|
2010-10-16 13:14:10 +00:00
|
|
|
filepath = PyBytes_AS_STRING(filebytes);
|
2010-06-17 23:08:50 +00:00
|
|
|
|
2010-05-09 15:52:27 +00:00
|
|
|
/* Search tail of filename in sys.path before giving up */
|
2010-06-17 23:08:50 +00:00
|
|
|
tail = strrchr(filepath, SEP);
|
2010-05-09 15:52:27 +00:00
|
|
|
if (tail == NULL)
|
2010-06-17 23:08:50 +00:00
|
|
|
tail = filepath;
|
2010-05-09 15:52:27 +00:00
|
|
|
else
|
|
|
|
tail++;
|
|
|
|
taillen = strlen(tail);
|
|
|
|
|
2022-02-08 13:39:07 -07:00
|
|
|
PyThreadState *tstate = _PyThreadState_GET();
|
2025-05-28 20:11:09 +03:00
|
|
|
if (PySys_GetOptionalAttr(&_Py_ID(path), &syspath) < 0) {
|
2025-02-25 23:04:27 +02:00
|
|
|
PyErr_Clear();
|
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
if (syspath == NULL || !PyList_Check(syspath)) {
|
2010-10-16 13:14:10 +00:00
|
|
|
goto error;
|
2025-02-25 23:04:27 +02:00
|
|
|
}
|
2010-06-17 23:08:50 +00:00
|
|
|
npath = PyList_Size(syspath);
|
2010-05-09 15:52:27 +00:00
|
|
|
|
2022-02-08 13:39:07 -07:00
|
|
|
open = PyObject_GetAttr(io, &_Py_ID(open));
|
2010-05-09 15:52:27 +00:00
|
|
|
for (i = 0; i < npath; i++) {
|
|
|
|
v = PyList_GetItem(syspath, i);
|
|
|
|
if (v == NULL) {
|
|
|
|
PyErr_Clear();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!PyUnicode_Check(v))
|
|
|
|
continue;
|
2010-10-16 13:14:10 +00:00
|
|
|
path = PyUnicode_EncodeFSDefault(v);
|
2010-06-17 23:08:50 +00:00
|
|
|
if (path == NULL) {
|
|
|
|
PyErr_Clear();
|
|
|
|
continue;
|
|
|
|
}
|
2010-10-16 13:14:10 +00:00
|
|
|
len = PyBytes_GET_SIZE(path);
|
|
|
|
if (len + 1 + (Py_ssize_t)taillen >= (Py_ssize_t)namelen - 1) {
|
|
|
|
Py_DECREF(path);
|
2010-05-09 15:52:27 +00:00
|
|
|
continue; /* Too long */
|
2010-10-16 13:14:10 +00:00
|
|
|
}
|
|
|
|
strcpy(namebuf, PyBytes_AS_STRING(path));
|
|
|
|
Py_DECREF(path);
|
2014-08-15 23:30:40 +02:00
|
|
|
if (strlen(namebuf) != (size_t)len)
|
2010-05-09 15:52:27 +00:00
|
|
|
continue; /* v contains '\0' */
|
|
|
|
if (len > 0 && namebuf[len-1] != SEP)
|
|
|
|
namebuf[len++] = SEP;
|
|
|
|
strcpy(namebuf+len, tail);
|
2010-06-17 23:08:50 +00:00
|
|
|
|
2022-02-08 13:39:07 -07:00
|
|
|
binary = _PyObject_CallMethodFormat(tstate, open, "ss", namebuf, "rb");
|
2010-10-16 13:14:10 +00:00
|
|
|
if (binary != NULL) {
|
|
|
|
result = binary;
|
|
|
|
goto finally;
|
|
|
|
}
|
2010-06-17 23:08:50 +00:00
|
|
|
PyErr_Clear();
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
2010-10-16 13:14:10 +00:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
error:
|
|
|
|
result = NULL;
|
|
|
|
finally:
|
2022-02-08 13:39:07 -07:00
|
|
|
Py_XDECREF(open);
|
2025-02-25 23:04:27 +02:00
|
|
|
Py_XDECREF(syspath);
|
2010-10-16 13:14:10 +00:00
|
|
|
Py_DECREF(filebytes);
|
|
|
|
return result;
|
2008-10-09 23:37:48 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 09:39:18 +00:00
|
|
|
/* Writes indent spaces. Returns 0 on success and non-zero on failure.
|
|
|
|
*/
|
|
|
|
int
|
|
|
|
_Py_WriteIndent(int indent, PyObject *f)
|
|
|
|
{
|
|
|
|
char buf[11] = " ";
|
|
|
|
assert(strlen(buf) == 10);
|
|
|
|
while (indent > 0) {
|
|
|
|
if (indent < 10) {
|
|
|
|
buf[indent] = '\0';
|
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
if (PyFile_WriteString(buf, f) < 0) {
|
|
|
|
return -1;
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
|
|
|
indent -= 10;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2023-10-12 16:52:14 +02:00
|
|
|
display_source_line(PyObject *f, PyObject *filename, int lineno, int indent,
|
|
|
|
int *truncation, PyObject **line)
|
1990-12-20 15:06:42 +00:00
|
|
|
{
|
2010-05-09 15:52:27 +00:00
|
|
|
int fd;
|
|
|
|
int i;
|
|
|
|
char *found_encoding;
|
2020-04-11 10:48:40 +03:00
|
|
|
const char *encoding;
|
2010-06-17 23:08:50 +00:00
|
|
|
PyObject *io;
|
|
|
|
PyObject *binary;
|
2010-05-09 15:52:27 +00:00
|
|
|
PyObject *fob = NULL;
|
|
|
|
PyObject *lineobj = NULL;
|
2010-10-14 21:15:17 +00:00
|
|
|
PyObject *res;
|
2010-05-09 15:52:27 +00:00
|
|
|
char buf[MAXPATHLEN+1];
|
2011-09-28 07:41:54 +02:00
|
|
|
int kind;
|
2020-04-11 10:48:40 +03:00
|
|
|
const void *data;
|
2010-05-09 15:52:27 +00:00
|
|
|
|
|
|
|
/* open the file */
|
|
|
|
if (filename == NULL)
|
|
|
|
return 0;
|
2010-06-17 23:08:50 +00:00
|
|
|
|
2021-09-20 16:10:30 +01:00
|
|
|
/* Do not attempt to open things like <string> or <stdin> */
|
|
|
|
assert(PyUnicode_Check(filename));
|
|
|
|
if (PyUnicode_READ_CHAR(filename, 0) == '<') {
|
|
|
|
Py_ssize_t len = PyUnicode_GET_LENGTH(filename);
|
|
|
|
if (len > 0 && PyUnicode_READ_CHAR(filename, len - 1) == '>') {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-12 14:15:20 +05:30
|
|
|
io = PyImport_ImportModule("io");
|
2022-02-08 13:39:07 -07:00
|
|
|
if (io == NULL) {
|
2010-06-17 23:08:50 +00:00
|
|
|
return -1;
|
2022-02-08 13:39:07 -07:00
|
|
|
}
|
2010-06-17 23:08:50 +00:00
|
|
|
|
2022-02-08 13:39:07 -07:00
|
|
|
binary = _PyObject_CallMethod(io, &_Py_ID(open), "Os", filename, "rb");
|
2010-06-17 23:08:50 +00:00
|
|
|
if (binary == NULL) {
|
2013-07-16 00:32:14 +02:00
|
|
|
PyErr_Clear();
|
|
|
|
|
2010-06-17 23:08:50 +00:00
|
|
|
binary = _Py_FindSourceFile(filename, buf, sizeof(buf), io);
|
|
|
|
if (binary == NULL) {
|
|
|
|
Py_DECREF(io);
|
2013-07-16 00:32:14 +02:00
|
|
|
return -1;
|
2010-06-17 23:08:50 +00:00
|
|
|
}
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* use the right encoding to decode the file as unicode */
|
2010-06-17 23:08:50 +00:00
|
|
|
fd = PyObject_AsFileDescriptor(binary);
|
2013-07-21 01:53:10 +02:00
|
|
|
if (fd < 0) {
|
|
|
|
Py_DECREF(io);
|
|
|
|
Py_DECREF(binary);
|
2013-07-21 13:26:13 -07:00
|
|
|
return 0;
|
2013-07-21 01:53:10 +02:00
|
|
|
}
|
2021-10-13 17:22:14 +02:00
|
|
|
found_encoding = _PyTokenizer_FindEncodingFilename(fd, filename);
|
2013-12-19 13:39:32 +01:00
|
|
|
if (found_encoding == NULL)
|
|
|
|
PyErr_Clear();
|
2010-06-17 23:08:50 +00:00
|
|
|
encoding = (found_encoding != NULL) ? found_encoding : "utf-8";
|
2013-07-21 02:12:35 +02:00
|
|
|
/* Reset position */
|
|
|
|
if (lseek(fd, 0, SEEK_SET) == (off_t)-1) {
|
|
|
|
Py_DECREF(io);
|
|
|
|
Py_DECREF(binary);
|
2020-12-01 09:56:42 +01:00
|
|
|
PyMem_Free(found_encoding);
|
2013-07-21 13:26:13 -07:00
|
|
|
return 0;
|
2013-07-21 02:12:35 +02:00
|
|
|
}
|
2022-02-08 13:39:07 -07:00
|
|
|
fob = _PyObject_CallMethod(io, &_Py_ID(TextIOWrapper),
|
|
|
|
"Os", binary, encoding);
|
2010-06-17 23:08:50 +00:00
|
|
|
Py_DECREF(io);
|
2020-12-01 09:56:42 +01:00
|
|
|
PyMem_Free(found_encoding);
|
2010-06-17 23:08:50 +00:00
|
|
|
|
2010-05-09 15:52:27 +00:00
|
|
|
if (fob == NULL) {
|
|
|
|
PyErr_Clear();
|
2015-03-25 02:25:25 +01:00
|
|
|
|
2022-02-08 13:39:07 -07:00
|
|
|
res = PyObject_CallMethodNoArgs(binary, &_Py_ID(close));
|
2015-03-25 02:25:25 +01:00
|
|
|
Py_DECREF(binary);
|
|
|
|
if (res)
|
|
|
|
Py_DECREF(res);
|
|
|
|
else
|
|
|
|
PyErr_Clear();
|
2010-05-09 15:52:27 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2015-03-25 02:25:25 +01:00
|
|
|
Py_DECREF(binary);
|
2010-05-09 15:52:27 +00:00
|
|
|
|
|
|
|
/* get the line number lineno */
|
|
|
|
for (i = 0; i < lineno; i++) {
|
|
|
|
Py_XDECREF(lineobj);
|
|
|
|
lineobj = PyFile_GetLine(fob, -1);
|
|
|
|
if (!lineobj) {
|
2014-10-30 10:17:27 +01:00
|
|
|
PyErr_Clear();
|
2010-05-09 15:52:27 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-02-08 13:39:07 -07:00
|
|
|
res = PyObject_CallMethodNoArgs(fob, &_Py_ID(close));
|
2021-12-07 16:17:22 +00:00
|
|
|
if (res) {
|
2010-10-14 21:15:17 +00:00
|
|
|
Py_DECREF(res);
|
2021-12-07 16:17:22 +00:00
|
|
|
}
|
|
|
|
else {
|
2010-10-14 21:15:17 +00:00
|
|
|
PyErr_Clear();
|
2021-12-07 16:17:22 +00:00
|
|
|
}
|
2010-05-09 15:52:27 +00:00
|
|
|
Py_DECREF(fob);
|
|
|
|
if (!lineobj || !PyUnicode_Check(lineobj)) {
|
|
|
|
Py_XDECREF(lineobj);
|
2021-12-07 16:17:22 +00:00
|
|
|
return -1;
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
|
|
|
|
2021-07-04 19:14:33 -04:00
|
|
|
if (line) {
|
2022-11-10 11:23:36 +01:00
|
|
|
*line = Py_NewRef(lineobj);
|
2021-07-04 19:14:33 -04:00
|
|
|
}
|
|
|
|
|
2010-05-09 15:52:27 +00:00
|
|
|
/* remove the indentation of the line */
|
2011-09-28 07:41:54 +02:00
|
|
|
kind = PyUnicode_KIND(lineobj);
|
|
|
|
data = PyUnicode_DATA(lineobj);
|
|
|
|
for (i=0; i < PyUnicode_GET_LENGTH(lineobj); i++) {
|
|
|
|
Py_UCS4 ch = PyUnicode_READ(kind, data, i);
|
|
|
|
if (ch != ' ' && ch != '\t' && ch != '\014')
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (i) {
|
2010-05-09 15:52:27 +00:00
|
|
|
PyObject *truncated;
|
2011-09-28 07:41:54 +02:00
|
|
|
truncated = PyUnicode_Substring(lineobj, i, PyUnicode_GET_LENGTH(lineobj));
|
2010-05-09 15:52:27 +00:00
|
|
|
if (truncated) {
|
2022-11-22 13:39:11 +01:00
|
|
|
Py_SETREF(lineobj, truncated);
|
2010-05-09 15:52:27 +00:00
|
|
|
} else {
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-04 19:14:33 -04:00
|
|
|
if (truncation != NULL) {
|
|
|
|
*truncation = i - indent;
|
|
|
|
}
|
|
|
|
|
2010-05-09 15:52:27 +00:00
|
|
|
/* Write some spaces before the line */
|
2021-12-07 16:17:22 +00:00
|
|
|
if (_Py_WriteIndent(indent, f) < 0) {
|
|
|
|
goto error;
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* finally display the line */
|
2021-12-07 16:17:22 +00:00
|
|
|
if (PyFile_WriteObject(lineobj, f, Py_PRINT_RAW) < 0) {
|
|
|
|
goto error;
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
|
|
|
|
if (PyFile_WriteString("\n", f) < 0) {
|
|
|
|
goto error;
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
|
|
|
|
Py_DECREF(lineobj);
|
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
Py_DECREF(lineobj);
|
|
|
|
return -1;
|
1990-12-20 15:06:42 +00:00
|
|
|
}
|
|
|
|
|
2021-11-05 09:39:18 +00:00
|
|
|
int
|
|
|
|
_Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,
|
|
|
|
int *truncation, PyObject **line)
|
|
|
|
{
|
2023-10-12 16:52:14 +02:00
|
|
|
return display_source_line(f, filename, lineno, indent, truncation, line);
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
|
|
|
|
2021-07-12 22:32:33 +03:00
|
|
|
|
|
|
|
#define IS_WHITESPACE(c) (((c) == ' ') || ((c) == '\t') || ((c) == '\f'))
|
2021-07-04 19:14:33 -04:00
|
|
|
#define _TRACEBACK_SOURCE_LINE_INDENT 4
|
|
|
|
|
2021-07-12 22:32:33 +03:00
|
|
|
static inline int
|
|
|
|
ignore_source_errors(void) {
|
|
|
|
if (PyErr_Occurred()) {
|
|
|
|
if (PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
PyErr_Clear();
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
1997-05-22 22:35:47 +00:00
|
|
|
static int
|
2021-07-04 19:14:33 -04:00
|
|
|
tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int lineno,
|
2023-10-12 16:52:14 +02:00
|
|
|
PyFrameObject *frame, PyObject *name)
|
Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,62302-62306,62308,62311,62313-62315,62319-62321 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines
better diagnostics
........
r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines
Raise SystemError when size < 0 is passed into PyString_FromStringAndSize,
PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587]
........
r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines
Remove the test file before writing it in case there is no write permission.
This might help fix some of the failures on Windows box(es). It doesn't hurt
either way and ensure the tests are a little more self contained (ie have
less assumptions).
........
r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines
get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code.
........
r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line
Remove forward-looking statement
........
r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line
Add punctuation
........
r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line
Use issue directive
........
r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines
Move backwards compatibility macro to the correct place;
PyIndex_Check() was introduced in Python 2.5.
........
r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines
Performance improvements.
........
r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines
Applied patch #2617 from Frank Wierzbicki wit some extras from me
-J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future.
........
r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines
Use absolute path in sys.path.
........
r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines
#2615: small consistency update by Jeroen Ruigrok van der Werven.
........
r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines
Add Jeroen.
........
r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines
Don't offend snake lovers.
........
r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines
fix compiler warnings
........
r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines
socket.error inherits from IOError, it no longer needs listing in
the all_errors tuple.
........
r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines
Re-implement the 'warnings' module in C. This allows for usage of the
'warnings' code in places where it was previously not possible (e.g., the
parser). It could also potentially lead to a speed-up in interpreter start-up
if the C version of the code (_warnings) is imported over the use of the
Python version in key places.
Closes issue #1631171.
........
r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines
Adds a profile-opt target for easy compilation of a python binary using
gcc's profile guided optimization.
........
r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix a bug in PySys_HasWarnOption() where it was not properly checking the
length of the list storing the warning options.
........
r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix an accidental bug of an non-existent init function.
........
r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line
Mention -J, -X
........
r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines
Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name
........
r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix test_warnings by making the state of things more consistent for each test
when it is run.
........
r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines
spelling
........
r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix markup.
........
r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line
Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file
........
r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line
Use PyString_InternFromString instead of PyString_FromString for static vars
........
r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line
Added new files to the pcbuild files
........
2008-04-13 13:53:33 +00:00
|
|
|
{
|
2021-12-07 16:17:22 +00:00
|
|
|
if (filename == NULL || name == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,62302-62306,62308,62311,62313-62315,62319-62321 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines
better diagnostics
........
r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines
Raise SystemError when size < 0 is passed into PyString_FromStringAndSize,
PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587]
........
r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines
Remove the test file before writing it in case there is no write permission.
This might help fix some of the failures on Windows box(es). It doesn't hurt
either way and ensure the tests are a little more self contained (ie have
less assumptions).
........
r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines
get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code.
........
r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line
Remove forward-looking statement
........
r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line
Add punctuation
........
r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line
Use issue directive
........
r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines
Move backwards compatibility macro to the correct place;
PyIndex_Check() was introduced in Python 2.5.
........
r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines
Performance improvements.
........
r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines
Applied patch #2617 from Frank Wierzbicki wit some extras from me
-J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future.
........
r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines
Use absolute path in sys.path.
........
r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines
#2615: small consistency update by Jeroen Ruigrok van der Werven.
........
r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines
Add Jeroen.
........
r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines
Don't offend snake lovers.
........
r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines
fix compiler warnings
........
r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines
socket.error inherits from IOError, it no longer needs listing in
the all_errors tuple.
........
r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines
Re-implement the 'warnings' module in C. This allows for usage of the
'warnings' code in places where it was previously not possible (e.g., the
parser). It could also potentially lead to a speed-up in interpreter start-up
if the C version of the code (_warnings) is imported over the use of the
Python version in key places.
Closes issue #1631171.
........
r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines
Adds a profile-opt target for easy compilation of a python binary using
gcc's profile guided optimization.
........
r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix a bug in PySys_HasWarnOption() where it was not properly checking the
length of the list storing the warning options.
........
r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix an accidental bug of an non-existent init function.
........
r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line
Mention -J, -X
........
r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines
Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name
........
r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix test_warnings by making the state of things more consistent for each test
when it is run.
........
r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines
spelling
........
r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix markup.
........
r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line
Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file
........
r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line
Use PyString_InternFromString instead of PyString_FromString for static vars
........
r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line
Added new files to the pcbuild files
........
2008-04-13 13:53:33 +00:00
|
|
|
|
2021-12-07 16:17:22 +00:00
|
|
|
PyObject *line = PyUnicode_FromFormat(" File \"%U\", line %d, in %U\n",
|
|
|
|
filename, lineno, name);
|
|
|
|
if (line == NULL) {
|
2010-06-17 23:08:50 +00:00
|
|
|
return -1;
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
|
|
|
|
int res = PyFile_WriteObject(line, f, Py_PRINT_RAW);
|
2010-06-17 23:08:50 +00:00
|
|
|
Py_DECREF(line);
|
2021-12-07 16:17:22 +00:00
|
|
|
if (res < 0) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
int err = 0;
|
2021-07-24 15:50:19 +03:00
|
|
|
|
2021-07-04 19:14:33 -04:00
|
|
|
int truncation = _TRACEBACK_SOURCE_LINE_INDENT;
|
|
|
|
PyObject* source_line = NULL;
|
2023-10-12 16:52:14 +02:00
|
|
|
int rc = display_source_line(
|
2021-11-05 09:39:18 +00:00
|
|
|
f, filename, lineno, _TRACEBACK_SOURCE_LINE_INDENT,
|
2023-10-12 16:52:14 +02:00
|
|
|
&truncation, &source_line);
|
2021-11-05 09:39:18 +00:00
|
|
|
if (rc != 0 || !source_line) {
|
2021-07-12 22:32:33 +03:00
|
|
|
/* ignore errors since we can't report them, can we? */
|
|
|
|
err = ignore_source_errors();
|
|
|
|
}
|
2021-07-04 19:14:33 -04:00
|
|
|
Py_XDECREF(source_line);
|
2012-07-19 21:02:03 +00:00
|
|
|
return err;
|
Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,62302-62306,62308,62311,62313-62315,62319-62321 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines
better diagnostics
........
r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines
Raise SystemError when size < 0 is passed into PyString_FromStringAndSize,
PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587]
........
r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines
Remove the test file before writing it in case there is no write permission.
This might help fix some of the failures on Windows box(es). It doesn't hurt
either way and ensure the tests are a little more self contained (ie have
less assumptions).
........
r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines
get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code.
........
r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line
Remove forward-looking statement
........
r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line
Add punctuation
........
r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line
Use issue directive
........
r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines
Move backwards compatibility macro to the correct place;
PyIndex_Check() was introduced in Python 2.5.
........
r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines
Performance improvements.
........
r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines
Applied patch #2617 from Frank Wierzbicki wit some extras from me
-J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future.
........
r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines
Use absolute path in sys.path.
........
r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines
#2615: small consistency update by Jeroen Ruigrok van der Werven.
........
r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines
Add Jeroen.
........
r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines
Don't offend snake lovers.
........
r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines
fix compiler warnings
........
r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines
socket.error inherits from IOError, it no longer needs listing in
the all_errors tuple.
........
r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines
Re-implement the 'warnings' module in C. This allows for usage of the
'warnings' code in places where it was previously not possible (e.g., the
parser). It could also potentially lead to a speed-up in interpreter start-up
if the C version of the code (_warnings) is imported over the use of the
Python version in key places.
Closes issue #1631171.
........
r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines
Adds a profile-opt target for easy compilation of a python binary using
gcc's profile guided optimization.
........
r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix a bug in PySys_HasWarnOption() where it was not properly checking the
length of the list storing the warning options.
........
r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix an accidental bug of an non-existent init function.
........
r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line
Mention -J, -X
........
r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines
Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name
........
r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix test_warnings by making the state of things more consistent for each test
when it is run.
........
r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines
spelling
........
r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix markup.
........
r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line
Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file
........
r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line
Use PyString_InternFromString instead of PyString_FromString for static vars
........
r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line
Added new files to the pcbuild files
........
2008-04-13 13:53:33 +00:00
|
|
|
}
|
|
|
|
|
2018-09-10 08:43:10 -07:00
|
|
|
static const int TB_RECURSIVE_CUTOFF = 3; // Also hardcoded in traceback.py.
|
|
|
|
|
2017-11-15 17:38:52 +02:00
|
|
|
static int
|
|
|
|
tb_print_line_repeated(PyObject *f, long cnt)
|
|
|
|
{
|
2018-09-10 08:43:10 -07:00
|
|
|
cnt -= TB_RECURSIVE_CUTOFF;
|
2017-11-15 17:38:52 +02:00
|
|
|
PyObject *line = PyUnicode_FromFormat(
|
2018-09-10 08:43:10 -07:00
|
|
|
(cnt > 1)
|
|
|
|
? " [Previous line repeated %ld more times]\n"
|
|
|
|
: " [Previous line repeated %ld more time]\n",
|
|
|
|
cnt);
|
2017-11-15 17:38:52 +02:00
|
|
|
if (line == NULL) {
|
|
|
|
return -1;
|
|
|
|
}
|
2018-09-10 08:43:10 -07:00
|
|
|
int err = PyFile_WriteObject(line, f, Py_PRINT_RAW);
|
2017-11-15 17:38:52 +02:00
|
|
|
Py_DECREF(line);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
Merged revisions 62260-62261,62266,62271,62277-62279,62289-62290,62293-62298,62302-62306,62308,62311,62313-62315,62319-62321 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk
........
r62260 | gregory.p.smith | 2008-04-10 01:11:56 +0200 (Thu, 10 Apr 2008) | 2 lines
better diagnostics
........
r62261 | gregory.p.smith | 2008-04-10 01:16:37 +0200 (Thu, 10 Apr 2008) | 3 lines
Raise SystemError when size < 0 is passed into PyString_FromStringAndSize,
PyBytes_FromStringAndSize or PyUnicode_FromStringAndSize. [issue2587]
........
r62266 | neal.norwitz | 2008-04-10 07:46:39 +0200 (Thu, 10 Apr 2008) | 5 lines
Remove the test file before writing it in case there is no write permission.
This might help fix some of the failures on Windows box(es). It doesn't hurt
either way and ensure the tests are a little more self contained (ie have
less assumptions).
........
r62271 | gregory.p.smith | 2008-04-10 21:50:36 +0200 (Thu, 10 Apr 2008) | 2 lines
get rid of assert (size >= 0) now that an explicit if (size < 0) is in the code.
........
r62277 | andrew.kuchling | 2008-04-10 23:27:10 +0200 (Thu, 10 Apr 2008) | 1 line
Remove forward-looking statement
........
r62278 | andrew.kuchling | 2008-04-10 23:28:51 +0200 (Thu, 10 Apr 2008) | 1 line
Add punctuation
........
r62279 | andrew.kuchling | 2008-04-10 23:29:01 +0200 (Thu, 10 Apr 2008) | 1 line
Use issue directive
........
r62289 | thomas.heller | 2008-04-11 15:05:38 +0200 (Fri, 11 Apr 2008) | 3 lines
Move backwards compatibility macro to the correct place;
PyIndex_Check() was introduced in Python 2.5.
........
r62290 | thomas.heller | 2008-04-11 16:20:26 +0200 (Fri, 11 Apr 2008) | 2 lines
Performance improvements.
........
r62293 | christian.heimes | 2008-04-12 15:03:03 +0200 (Sat, 12 Apr 2008) | 2 lines
Applied patch #2617 from Frank Wierzbicki wit some extras from me
-J and -X are now reserved for Jython and non-standard arguments (e.g. IronPython). I've added some extra comments to make sure the reservation don't get missed in the future.
........
r62294 | georg.brandl | 2008-04-12 20:11:18 +0200 (Sat, 12 Apr 2008) | 2 lines
Use absolute path in sys.path.
........
r62295 | georg.brandl | 2008-04-12 20:36:09 +0200 (Sat, 12 Apr 2008) | 2 lines
#2615: small consistency update by Jeroen Ruigrok van der Werven.
........
r62296 | georg.brandl | 2008-04-12 21:00:20 +0200 (Sat, 12 Apr 2008) | 2 lines
Add Jeroen.
........
r62297 | georg.brandl | 2008-04-12 21:05:37 +0200 (Sat, 12 Apr 2008) | 2 lines
Don't offend snake lovers.
........
r62298 | gregory.p.smith | 2008-04-12 22:37:48 +0200 (Sat, 12 Apr 2008) | 2 lines
fix compiler warnings
........
r62302 | gregory.p.smith | 2008-04-13 00:24:04 +0200 (Sun, 13 Apr 2008) | 3 lines
socket.error inherits from IOError, it no longer needs listing in
the all_errors tuple.
........
r62303 | brett.cannon | 2008-04-13 01:44:07 +0200 (Sun, 13 Apr 2008) | 8 lines
Re-implement the 'warnings' module in C. This allows for usage of the
'warnings' code in places where it was previously not possible (e.g., the
parser). It could also potentially lead to a speed-up in interpreter start-up
if the C version of the code (_warnings) is imported over the use of the
Python version in key places.
Closes issue #1631171.
........
r62304 | gregory.p.smith | 2008-04-13 02:03:25 +0200 (Sun, 13 Apr 2008) | 3 lines
Adds a profile-opt target for easy compilation of a python binary using
gcc's profile guided optimization.
........
r62305 | brett.cannon | 2008-04-13 02:18:44 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix a bug in PySys_HasWarnOption() where it was not properly checking the
length of the list storing the warning options.
........
r62306 | brett.cannon | 2008-04-13 02:25:15 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix an accidental bug of an non-existent init function.
........
r62308 | andrew.kuchling | 2008-04-13 03:05:59 +0200 (Sun, 13 Apr 2008) | 1 line
Mention -J, -X
........
r62311 | benjamin.peterson | 2008-04-13 04:20:05 +0200 (Sun, 13 Apr 2008) | 2 lines
Give the "Interactive Interpreter Changes" section in 2.6 whatsnew a unique link name
........
r62313 | brett.cannon | 2008-04-13 04:42:36 +0200 (Sun, 13 Apr 2008) | 3 lines
Fix test_warnings by making the state of things more consistent for each test
when it is run.
........
r62314 | skip.montanaro | 2008-04-13 05:17:30 +0200 (Sun, 13 Apr 2008) | 2 lines
spelling
........
r62315 | georg.brandl | 2008-04-13 09:07:44 +0200 (Sun, 13 Apr 2008) | 2 lines
Fix markup.
........
r62319 | christian.heimes | 2008-04-13 11:30:17 +0200 (Sun, 13 Apr 2008) | 1 line
Fix compiler warning Include/warnings.h:19:28: warning: no newline at end of file
........
r62320 | christian.heimes | 2008-04-13 11:33:24 +0200 (Sun, 13 Apr 2008) | 1 line
Use PyString_InternFromString instead of PyString_FromString for static vars
........
r62321 | christian.heimes | 2008-04-13 11:37:05 +0200 (Sun, 13 Apr 2008) | 1 line
Added new files to the pcbuild files
........
2008-04-13 13:53:33 +00:00
|
|
|
static int
|
2023-10-12 16:52:14 +02:00
|
|
|
tb_printinternal(PyTracebackObject *tb, PyObject *f, long limit)
|
1990-12-20 15:06:42 +00:00
|
|
|
{
|
2021-12-07 16:17:22 +00:00
|
|
|
PyCodeObject *code = NULL;
|
2017-11-15 17:38:52 +02:00
|
|
|
Py_ssize_t depth = 0;
|
2016-08-15 13:11:34 +10:00
|
|
|
PyObject *last_file = NULL;
|
|
|
|
int last_line = -1;
|
|
|
|
PyObject *last_name = NULL;
|
|
|
|
long cnt = 0;
|
2010-05-09 15:52:27 +00:00
|
|
|
PyTracebackObject *tb1 = tb;
|
|
|
|
while (tb1 != NULL) {
|
|
|
|
depth++;
|
|
|
|
tb1 = tb1->tb_next;
|
|
|
|
}
|
2017-11-15 17:38:52 +02:00
|
|
|
while (tb != NULL && depth > limit) {
|
|
|
|
depth--;
|
|
|
|
tb = tb->tb_next;
|
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
while (tb != NULL) {
|
|
|
|
code = PyFrame_GetCode(tb->tb_frame);
|
2023-10-31 15:02:31 +00:00
|
|
|
int tb_lineno = tb->tb_lineno;
|
|
|
|
if (tb_lineno == -1) {
|
2025-01-27 15:07:39 +01:00
|
|
|
tb_lineno = tb_get_lineno((PyObject *)tb);
|
2023-10-31 15:02:31 +00:00
|
|
|
}
|
2018-09-10 08:43:10 -07:00
|
|
|
if (last_file == NULL ||
|
2020-04-28 19:01:31 +02:00
|
|
|
code->co_filename != last_file ||
|
2023-10-31 15:02:31 +00:00
|
|
|
last_line == -1 || tb_lineno != last_line ||
|
2020-04-28 19:01:31 +02:00
|
|
|
last_name == NULL || code->co_name != last_name) {
|
2018-09-10 08:43:10 -07:00
|
|
|
if (cnt > TB_RECURSIVE_CUTOFF) {
|
2021-12-07 16:17:22 +00:00
|
|
|
if (tb_print_line_repeated(f, cnt) < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
2017-11-15 17:38:52 +02:00
|
|
|
}
|
2020-04-28 19:01:31 +02:00
|
|
|
last_file = code->co_filename;
|
2023-10-31 15:02:31 +00:00
|
|
|
last_line = tb_lineno;
|
2020-04-28 19:01:31 +02:00
|
|
|
last_name = code->co_name;
|
2017-11-15 17:38:52 +02:00
|
|
|
cnt = 0;
|
|
|
|
}
|
2018-09-10 08:43:10 -07:00
|
|
|
cnt++;
|
2021-12-07 16:17:22 +00:00
|
|
|
if (cnt <= TB_RECURSIVE_CUTOFF) {
|
2023-10-31 15:02:31 +00:00
|
|
|
if (tb_displayline(tb, f, code->co_filename, tb_lineno,
|
2023-10-12 16:52:14 +02:00
|
|
|
tb->tb_frame, code->co_name) < 0) {
|
2021-12-07 16:17:22 +00:00
|
|
|
goto error;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (PyErr_CheckSignals() < 0) {
|
|
|
|
goto error;
|
2017-11-15 17:38:52 +02:00
|
|
|
}
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
Py_CLEAR(code);
|
2010-05-09 15:52:27 +00:00
|
|
|
tb = tb->tb_next;
|
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
if (cnt > TB_RECURSIVE_CUTOFF) {
|
|
|
|
if (tb_print_line_repeated(f, cnt) < 0) {
|
|
|
|
goto error;
|
|
|
|
}
|
2016-08-15 13:11:34 +10:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
return 0;
|
|
|
|
error:
|
|
|
|
Py_XDECREF(code);
|
|
|
|
return -1;
|
1990-12-20 15:06:42 +00:00
|
|
|
}
|
|
|
|
|
2007-12-04 21:55:18 +00:00
|
|
|
#define PyTraceBack_LIMIT 1000
|
|
|
|
|
1990-12-20 15:06:42 +00:00
|
|
|
int
|
2023-10-12 16:52:14 +02:00
|
|
|
_PyTraceBack_Print(PyObject *v, const char *header, PyObject *f)
|
1990-12-20 15:06:42 +00:00
|
|
|
{
|
2010-05-09 15:52:27 +00:00
|
|
|
PyObject *limitv;
|
|
|
|
long limit = PyTraceBack_LIMIT;
|
|
|
|
|
2021-12-07 16:17:22 +00:00
|
|
|
if (v == NULL) {
|
2010-05-09 15:52:27 +00:00
|
|
|
return 0;
|
2021-12-07 16:17:22 +00:00
|
|
|
}
|
2010-05-09 15:52:27 +00:00
|
|
|
if (!PyTraceBack_Check(v)) {
|
|
|
|
PyErr_BadInternalCall();
|
|
|
|
return -1;
|
|
|
|
}
|
2025-05-28 20:11:09 +03:00
|
|
|
if (PySys_GetOptionalAttrString("tracebacklimit", &limitv) < 0) {
|
2025-02-25 23:04:27 +02:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
else if (limitv != NULL && PyLong_Check(limitv)) {
|
2017-11-15 17:38:52 +02:00
|
|
|
int overflow;
|
|
|
|
limit = PyLong_AsLongAndOverflow(limitv, &overflow);
|
|
|
|
if (overflow > 0) {
|
|
|
|
limit = LONG_MAX;
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
|
|
|
else if (limit <= 0) {
|
2025-02-25 23:04:27 +02:00
|
|
|
Py_DECREF(limitv);
|
2017-11-15 17:38:52 +02:00
|
|
|
return 0;
|
2010-05-09 15:52:27 +00:00
|
|
|
}
|
|
|
|
}
|
2025-02-25 23:04:27 +02:00
|
|
|
Py_XDECREF(limitv);
|
2021-12-07 16:17:22 +00:00
|
|
|
|
|
|
|
if (PyFile_WriteString(header, f) < 0) {
|
|
|
|
return -1;
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
|
2023-10-12 16:52:14 +02:00
|
|
|
if (tb_printinternal((PyTracebackObject *)v, f, limit) < 0) {
|
2021-12-07 16:17:22 +00:00
|
|
|
return -1;
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
2021-12-07 16:17:22 +00:00
|
|
|
|
|
|
|
return 0;
|
1990-12-20 15:06:42 +00:00
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
|
2021-11-05 09:39:18 +00:00
|
|
|
int
|
|
|
|
PyTraceBack_Print(PyObject *v, PyObject *f)
|
|
|
|
{
|
|
|
|
const char *header = EXCEPTION_TB_HEADER;
|
2023-10-12 16:52:14 +02:00
|
|
|
return _PyTraceBack_Print(v, header, f);
|
2021-11-05 09:39:18 +00:00
|
|
|
}
|
|
|
|
|
2020-12-17 12:33:07 +00:00
|
|
|
/* Format an integer in range [0; 0xffffffff] to decimal and write it
|
|
|
|
into the file fd.
|
2011-03-31 01:31:06 +02:00
|
|
|
|
|
|
|
This function is signal safe. */
|
|
|
|
|
2016-03-15 21:49:37 +01:00
|
|
|
void
|
2021-01-19 23:35:27 +01:00
|
|
|
_Py_DumpDecimal(int fd, size_t value)
|
2011-03-31 01:31:06 +02:00
|
|
|
{
|
2016-03-15 21:49:37 +01:00
|
|
|
/* maximum number of characters required for output of %lld or %p.
|
|
|
|
We need at most ceil(log10(256)*SIZEOF_LONG_LONG) digits,
|
|
|
|
plus 1 for the null byte. 53/22 is an upper bound for log10(256). */
|
2021-01-19 23:35:27 +01:00
|
|
|
char buffer[1 + (sizeof(size_t)*53-1) / 22 + 1];
|
2016-03-15 21:49:37 +01:00
|
|
|
char *ptr, *end;
|
|
|
|
|
|
|
|
end = &buffer[Py_ARRAY_LENGTH(buffer) - 1];
|
|
|
|
ptr = end;
|
|
|
|
*ptr = '\0';
|
2011-03-31 01:31:06 +02:00
|
|
|
do {
|
2016-03-15 21:49:37 +01:00
|
|
|
--ptr;
|
|
|
|
assert(ptr >= buffer);
|
|
|
|
*ptr = '0' + (value % 10);
|
2011-03-31 01:31:06 +02:00
|
|
|
value /= 10;
|
|
|
|
} while (value);
|
2016-03-15 21:49:37 +01:00
|
|
|
|
2023-08-22 16:28:20 +02:00
|
|
|
(void)_Py_write_noraise(fd, ptr, end - ptr);
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
|
2021-01-18 18:34:56 +01:00
|
|
|
/* Format an integer as hexadecimal with width digits into fd file descriptor.
|
|
|
|
The function is signal safe. */
|
2025-04-23 22:02:25 +02:00
|
|
|
static void
|
|
|
|
dump_hexadecimal(int fd, uintptr_t value, Py_ssize_t width, int strip_zeros)
|
2011-03-31 01:31:06 +02:00
|
|
|
{
|
2021-01-18 18:34:56 +01:00
|
|
|
char buffer[sizeof(uintptr_t) * 2 + 1], *ptr, *end;
|
2025-04-23 22:02:25 +02:00
|
|
|
Py_ssize_t size = Py_ARRAY_LENGTH(buffer) - 1;
|
2016-03-15 21:49:37 +01:00
|
|
|
|
|
|
|
if (width > size)
|
|
|
|
width = size;
|
2016-03-23 10:32:26 +01:00
|
|
|
/* it's ok if width is negative */
|
2016-03-15 21:49:37 +01:00
|
|
|
|
2016-03-16 09:43:14 +01:00
|
|
|
end = &buffer[size];
|
2016-03-15 21:49:37 +01:00
|
|
|
ptr = end;
|
|
|
|
*ptr = '\0';
|
2011-03-31 01:31:06 +02:00
|
|
|
do {
|
2016-03-15 21:49:37 +01:00
|
|
|
--ptr;
|
|
|
|
assert(ptr >= buffer);
|
|
|
|
*ptr = Py_hexdigits[value & 15];
|
2011-03-31 01:31:06 +02:00
|
|
|
value >>= 4;
|
2016-03-15 21:49:37 +01:00
|
|
|
} while ((end - ptr) < width || value);
|
2011-03-31 01:31:06 +02:00
|
|
|
|
2025-04-23 22:02:25 +02:00
|
|
|
size = end - ptr;
|
|
|
|
if (strip_zeros) {
|
|
|
|
while (*ptr == '0' && size >= 2) {
|
|
|
|
ptr++;
|
|
|
|
size--;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
(void)_Py_write_noraise(fd, ptr, size);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_Py_DumpHexadecimal(int fd, uintptr_t value, Py_ssize_t width)
|
|
|
|
{
|
|
|
|
dump_hexadecimal(fd, value, width, 0);
|
|
|
|
}
|
|
|
|
|
2025-04-25 09:28:34 +02:00
|
|
|
#ifdef CAN_C_BACKTRACE
|
2025-04-23 22:02:25 +02:00
|
|
|
static void
|
|
|
|
dump_pointer(int fd, void *ptr)
|
|
|
|
{
|
|
|
|
PUTS(fd, "0x");
|
|
|
|
dump_hexadecimal(fd, (uintptr_t)ptr, sizeof(void*), 1);
|
|
|
|
}
|
2025-04-25 09:28:34 +02:00
|
|
|
#endif
|
2025-04-23 22:02:25 +02:00
|
|
|
|
|
|
|
static void
|
|
|
|
dump_char(int fd, char ch)
|
|
|
|
{
|
|
|
|
char buf[1] = {ch};
|
|
|
|
(void)_Py_write_noraise(fd, buf, 1);
|
2016-03-15 21:49:37 +01:00
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
|
2016-03-15 21:49:37 +01:00
|
|
|
void
|
|
|
|
_Py_DumpASCII(int fd, PyObject *text)
|
2011-03-31 01:31:06 +02:00
|
|
|
{
|
2022-03-31 09:59:27 +02:00
|
|
|
PyASCIIObject *ascii = _PyASCIIObject_CAST(text);
|
2011-03-31 01:31:06 +02:00
|
|
|
Py_ssize_t i, size;
|
|
|
|
int truncated;
|
2011-09-28 07:41:54 +02:00
|
|
|
int kind;
|
2011-10-05 22:44:12 +02:00
|
|
|
void *data = NULL;
|
2011-09-28 07:41:54 +02:00
|
|
|
Py_UCS4 ch;
|
|
|
|
|
2016-03-15 21:49:37 +01:00
|
|
|
if (!PyUnicode_Check(text))
|
|
|
|
return;
|
|
|
|
|
2011-09-28 07:41:54 +02:00
|
|
|
size = ascii->length;
|
|
|
|
kind = ascii->state.kind;
|
2022-05-12 14:48:38 +09:00
|
|
|
if (ascii->state.compact) {
|
2011-09-28 07:41:54 +02:00
|
|
|
if (ascii->state.ascii)
|
2022-03-31 09:59:27 +02:00
|
|
|
data = ascii + 1;
|
2011-09-28 07:41:54 +02:00
|
|
|
else
|
2022-03-31 09:59:27 +02:00
|
|
|
data = _PyCompactUnicodeObject_CAST(text) + 1;
|
2011-09-28 07:41:54 +02:00
|
|
|
}
|
2016-03-23 16:10:07 +01:00
|
|
|
else {
|
2022-03-31 09:59:27 +02:00
|
|
|
data = _PyUnicodeObject_CAST(text)->data.any;
|
2011-09-28 07:41:54 +02:00
|
|
|
if (data == NULL)
|
|
|
|
return;
|
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
|
|
|
|
if (MAX_STRING_LENGTH < size) {
|
|
|
|
size = MAX_STRING_LENGTH;
|
|
|
|
truncated = 1;
|
|
|
|
}
|
2016-03-15 21:49:37 +01:00
|
|
|
else {
|
2011-03-31 01:31:06 +02:00
|
|
|
truncated = 0;
|
2016-03-15 21:49:37 +01:00
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
|
2021-11-17 21:12:20 +01:00
|
|
|
// Is an ASCII string?
|
|
|
|
if (ascii->state.ascii) {
|
|
|
|
assert(kind == PyUnicode_1BYTE_KIND);
|
|
|
|
char *str = data;
|
|
|
|
|
|
|
|
int need_escape = 0;
|
|
|
|
for (i=0; i < size; i++) {
|
|
|
|
ch = str[i];
|
|
|
|
if (!(' ' <= ch && ch <= 126)) {
|
|
|
|
need_escape = 1;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (!need_escape) {
|
|
|
|
// The string can be written with a single write() syscall
|
2023-08-22 16:28:20 +02:00
|
|
|
(void)_Py_write_noraise(fd, str, size);
|
2021-11-17 21:12:20 +01:00
|
|
|
goto done;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-28 07:41:54 +02:00
|
|
|
for (i=0; i < size; i++) {
|
2022-05-12 14:48:38 +09:00
|
|
|
ch = PyUnicode_READ(kind, data, i);
|
2014-10-03 14:18:09 +02:00
|
|
|
if (' ' <= ch && ch <= 126) {
|
|
|
|
/* printable ASCII character */
|
2025-04-23 22:02:25 +02:00
|
|
|
dump_char(fd, (char)ch);
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
2014-10-03 14:18:09 +02:00
|
|
|
else if (ch <= 0xff) {
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, "\\x");
|
2016-03-23 10:32:26 +01:00
|
|
|
_Py_DumpHexadecimal(fd, ch, 2);
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
2014-10-03 14:18:09 +02:00
|
|
|
else if (ch <= 0xffff) {
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, "\\u");
|
2016-03-23 10:32:26 +01:00
|
|
|
_Py_DumpHexadecimal(fd, ch, 4);
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
PUTS(fd, "\\U");
|
2016-03-23 10:32:26 +01:00
|
|
|
_Py_DumpHexadecimal(fd, ch, 8);
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
}
|
2021-11-17 21:12:20 +01:00
|
|
|
|
|
|
|
done:
|
2016-03-15 21:49:37 +01:00
|
|
|
if (truncated) {
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, "...");
|
2016-03-15 21:49:37 +01:00
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Write a frame into the file fd: "File "xxx", line xxx in xxx".
|
|
|
|
|
|
|
|
This function is signal safe. */
|
|
|
|
|
|
|
|
static void
|
2022-02-25 16:22:00 +01:00
|
|
|
dump_frame(int fd, _PyInterpreterFrame *frame)
|
2011-03-31 01:31:06 +02:00
|
|
|
{
|
2025-01-21 10:15:02 +00:00
|
|
|
assert(frame->owner < FRAME_OWNED_BY_INTERPRETER);
|
2024-11-27 16:14:49 +01:00
|
|
|
|
2023-06-14 13:46:37 +01:00
|
|
|
PyCodeObject *code =_PyFrame_GetCode(frame);
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, " File ");
|
2020-04-29 01:28:13 +02:00
|
|
|
if (code->co_filename != NULL
|
2011-03-31 01:31:06 +02:00
|
|
|
&& PyUnicode_Check(code->co_filename))
|
|
|
|
{
|
2015-04-01 18:38:01 +02:00
|
|
|
PUTS(fd, "\"");
|
2016-03-15 21:49:37 +01:00
|
|
|
_Py_DumpASCII(fd, code->co_filename);
|
2015-04-01 18:38:01 +02:00
|
|
|
PUTS(fd, "\"");
|
2011-03-31 01:31:06 +02:00
|
|
|
} else {
|
|
|
|
PUTS(fd, "???");
|
|
|
|
}
|
|
|
|
|
2023-05-05 17:53:07 +01:00
|
|
|
int lineno = PyUnstable_InterpreterFrame_GetLine(frame);
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, ", line ");
|
2016-03-15 21:49:37 +01:00
|
|
|
if (lineno >= 0) {
|
2021-01-19 23:35:27 +01:00
|
|
|
_Py_DumpDecimal(fd, (size_t)lineno);
|
2016-03-15 21:49:37 +01:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
PUTS(fd, "???");
|
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, " in ");
|
|
|
|
|
2020-04-29 01:28:13 +02:00
|
|
|
if (code->co_name != NULL
|
2016-03-15 21:49:37 +01:00
|
|
|
&& PyUnicode_Check(code->co_name)) {
|
|
|
|
_Py_DumpASCII(fd, code->co_name);
|
|
|
|
}
|
|
|
|
else {
|
2011-03-31 01:31:06 +02:00
|
|
|
PUTS(fd, "???");
|
2016-03-15 21:49:37 +01:00
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
|
2015-04-01 18:38:01 +02:00
|
|
|
PUTS(fd, "\n");
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
|
2023-09-29 04:04:06 +02:00
|
|
|
static int
|
|
|
|
tstate_is_freed(PyThreadState *tstate)
|
|
|
|
{
|
|
|
|
if (_PyMem_IsPtrFreed(tstate)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (_PyMem_IsPtrFreed(tstate->interp)) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
interp_is_freed(PyInterpreterState *interp)
|
|
|
|
{
|
|
|
|
return _PyMem_IsPtrFreed(interp);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-01 15:34:01 +02:00
|
|
|
static void
|
2011-03-31 01:31:06 +02:00
|
|
|
dump_traceback(int fd, PyThreadState *tstate, int write_header)
|
|
|
|
{
|
2019-09-17 23:36:16 +02:00
|
|
|
if (write_header) {
|
2013-10-20 18:21:02 -07:00
|
|
|
PUTS(fd, "Stack (most recent call first):\n");
|
2019-09-17 23:36:16 +02:00
|
|
|
}
|
2011-04-01 15:34:01 +02:00
|
|
|
|
2023-09-29 04:04:06 +02:00
|
|
|
if (tstate_is_freed(tstate)) {
|
|
|
|
PUTS(fd, " <tstate is freed>\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_PyInterpreterFrame *frame = tstate->current_frame;
|
2019-09-17 23:36:16 +02:00
|
|
|
if (frame == NULL) {
|
2021-08-31 17:34:29 +02:00
|
|
|
PUTS(fd, " <no Python frame>\n");
|
2011-04-01 15:34:01 +02:00
|
|
|
return;
|
2019-09-17 23:36:16 +02:00
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
|
2023-09-29 04:04:06 +02:00
|
|
|
unsigned int depth = 0;
|
2020-04-29 03:28:46 +02:00
|
|
|
while (1) {
|
2025-01-21 10:15:02 +00:00
|
|
|
if (frame->owner == FRAME_OWNED_BY_INTERPRETER) {
|
2024-11-27 16:14:49 +01:00
|
|
|
/* Trampoline frame */
|
|
|
|
frame = frame->previous;
|
|
|
|
if (frame == NULL) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Can't have more than one shim frame in a row */
|
2025-01-21 10:15:02 +00:00
|
|
|
assert(frame->owner != FRAME_OWNED_BY_INTERPRETER);
|
2024-11-27 16:14:49 +01:00
|
|
|
}
|
|
|
|
|
2011-03-31 01:31:06 +02:00
|
|
|
if (MAX_FRAME_DEPTH <= depth) {
|
2024-01-16 09:32:01 +00:00
|
|
|
if (MAX_FRAME_DEPTH < depth) {
|
|
|
|
PUTS(fd, "plus ");
|
|
|
|
_Py_DumpDecimal(fd, depth);
|
|
|
|
PUTS(fd, " frames\n");
|
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
break;
|
|
|
|
}
|
2024-11-27 16:14:49 +01:00
|
|
|
|
2011-03-31 01:31:06 +02:00
|
|
|
dump_frame(fd, frame);
|
2021-07-26 11:22:16 +01:00
|
|
|
frame = frame->previous;
|
|
|
|
if (frame == NULL) {
|
2020-04-29 03:28:46 +02:00
|
|
|
break;
|
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
depth++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-01 18:38:01 +02:00
|
|
|
/* 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. */
|
2011-04-01 15:34:01 +02:00
|
|
|
void
|
2011-03-31 01:31:06 +02:00
|
|
|
_Py_DumpTraceback(int fd, PyThreadState *tstate)
|
|
|
|
{
|
2011-04-01 15:34:01 +02:00
|
|
|
dump_traceback(fd, tstate, 1);
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
|
2025-04-12 11:25:35 +03:00
|
|
|
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
|
|
|
|
# if defined(__OpenBSD__)
|
|
|
|
/* pthread_*_np functions, especially pthread_{get,set}_name_np().
|
|
|
|
pthread_np.h exists on both OpenBSD and FreeBSD but the latter declares
|
|
|
|
pthread_getname_np() and pthread_setname_np() in pthread.h as long as
|
|
|
|
__BSD_VISIBLE remains set.
|
|
|
|
*/
|
|
|
|
# include <pthread_np.h>
|
|
|
|
# endif
|
|
|
|
#endif
|
|
|
|
|
2011-03-31 01:31:06 +02:00
|
|
|
/* Write the thread identifier into the file 'fd': "Current thread 0xHHHH:\" if
|
|
|
|
is_current is true, "Thread 0xHHHH:\n" otherwise.
|
|
|
|
|
|
|
|
This function is signal safe. */
|
|
|
|
|
|
|
|
static void
|
|
|
|
write_thread_id(int fd, PyThreadState *tstate, int is_current)
|
|
|
|
{
|
|
|
|
if (is_current)
|
|
|
|
PUTS(fd, "Current thread 0x");
|
|
|
|
else
|
|
|
|
PUTS(fd, "Thread 0x");
|
2016-03-23 10:32:26 +01:00
|
|
|
_Py_DumpHexadecimal(fd,
|
2017-03-23 15:48:39 +02:00
|
|
|
tstate->thread_id,
|
2016-03-23 10:32:26 +01:00
|
|
|
sizeof(unsigned long) * 2);
|
2025-04-04 14:24:41 +02:00
|
|
|
|
|
|
|
// Write the thread name
|
|
|
|
#if defined(HAVE_PTHREAD_GETNAME_NP) || defined(HAVE_PTHREAD_GET_NAME_NP)
|
|
|
|
char name[100];
|
|
|
|
pthread_t thread = (pthread_t)tstate->thread_id;
|
|
|
|
#ifdef HAVE_PTHREAD_GETNAME_NP
|
|
|
|
int rc = pthread_getname_np(thread, name, Py_ARRAY_LENGTH(name));
|
|
|
|
#else /* defined(HAVE_PTHREAD_GET_NAME_NP) */
|
|
|
|
int rc = 0; /* pthread_get_name_np() returns void */
|
|
|
|
pthread_get_name_np(thread, name, Py_ARRAY_LENGTH(name));
|
|
|
|
#endif
|
|
|
|
if (!rc) {
|
|
|
|
size_t len = strlen(name);
|
|
|
|
if (len) {
|
|
|
|
PUTS(fd, " [");
|
|
|
|
(void)_Py_write_noraise(fd, name, len);
|
|
|
|
PUTS(fd, "]");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2013-10-20 18:21:02 -07:00
|
|
|
PUTS(fd, " (most recent call first):\n");
|
2011-03-31 01:31:06 +02:00
|
|
|
}
|
|
|
|
|
2015-04-01 18:38:01 +02:00
|
|
|
/* 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. */
|
2011-03-31 01:31:06 +02:00
|
|
|
const char*
|
|
|
|
_Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
|
2016-03-16 22:45:24 +01:00
|
|
|
PyThreadState *current_tstate)
|
2011-03-31 01:31:06 +02:00
|
|
|
{
|
2016-03-16 22:45:24 +01:00
|
|
|
if (current_tstate == NULL) {
|
|
|
|
/* _Py_DumpTracebackThreads() is called from signal handlers by
|
|
|
|
faulthandler.
|
|
|
|
|
|
|
|
SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals
|
|
|
|
and are thus delivered to the thread that caused the fault. Get the
|
|
|
|
Python thread state of the current thread.
|
|
|
|
|
|
|
|
PyThreadState_Get() doesn't give the state of the thread that caused
|
2019-09-17 23:36:16 +02:00
|
|
|
the fault if the thread released the GIL, and so
|
|
|
|
_PyThreadState_GET() cannot be used. Read the thread specific
|
|
|
|
storage (TSS) instead: call PyGILState_GetThisThreadState(). */
|
2016-03-16 22:45:24 +01:00
|
|
|
current_tstate = PyGILState_GetThisThreadState();
|
|
|
|
}
|
|
|
|
|
2023-09-29 04:04:06 +02:00
|
|
|
if (current_tstate != NULL && tstate_is_freed(current_tstate)) {
|
|
|
|
return "tstate is freed";
|
|
|
|
}
|
|
|
|
|
2016-03-16 22:45:24 +01:00
|
|
|
if (interp == NULL) {
|
|
|
|
if (current_tstate == NULL) {
|
|
|
|
interp = _PyGILState_GetInterpreterStateUnsafe();
|
|
|
|
if (interp == NULL) {
|
|
|
|
/* We need the interpreter state to get Python threads */
|
|
|
|
return "unable to get the interpreter state";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
interp = current_tstate->interp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert(interp != NULL);
|
|
|
|
|
2023-09-29 04:04:06 +02:00
|
|
|
if (interp_is_freed(interp)) {
|
|
|
|
return "interp is freed";
|
|
|
|
}
|
|
|
|
|
2011-03-31 01:31:06 +02:00
|
|
|
/* Get the current interpreter from the current thread */
|
2023-09-29 04:04:06 +02:00
|
|
|
PyThreadState *tstate = PyInterpreterState_ThreadHead(interp);
|
2011-03-31 01:31:06 +02:00
|
|
|
if (tstate == NULL)
|
|
|
|
return "unable to get the thread head state";
|
|
|
|
|
|
|
|
/* Dump the traceback of each thread */
|
|
|
|
tstate = PyInterpreterState_ThreadHead(interp);
|
2023-09-29 04:04:06 +02:00
|
|
|
unsigned int nthreads = 0;
|
2015-04-12 00:26:27 -04:00
|
|
|
_Py_BEGIN_SUPPRESS_IPH
|
2011-03-31 01:31:06 +02:00
|
|
|
do
|
|
|
|
{
|
|
|
|
if (nthreads != 0)
|
2015-04-01 18:38:01 +02:00
|
|
|
PUTS(fd, "\n");
|
2011-03-31 01:31:06 +02:00
|
|
|
if (nthreads >= MAX_NTHREADS) {
|
|
|
|
PUTS(fd, "...\n");
|
|
|
|
break;
|
|
|
|
}
|
2016-03-16 22:45:24 +01:00
|
|
|
write_thread_id(fd, tstate, tstate == current_tstate);
|
2021-06-21 13:15:40 +02:00
|
|
|
if (tstate == current_tstate && tstate->interp->gc.collecting) {
|
|
|
|
PUTS(fd, " Garbage-collecting\n");
|
|
|
|
}
|
2011-03-31 01:31:06 +02:00
|
|
|
dump_traceback(fd, tstate, 0);
|
|
|
|
tstate = PyThreadState_Next(tstate);
|
|
|
|
nthreads++;
|
|
|
|
} while (tstate != NULL);
|
2015-04-12 00:26:27 -04:00
|
|
|
_Py_END_SUPPRESS_IPH
|
2011-03-31 01:31:06 +02:00
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2025-04-21 15:48:02 -04:00
|
|
|
#ifdef CAN_C_BACKTRACE
|
|
|
|
/* Based on glibc's implementation of backtrace_symbols(), but only uses stack memory. */
|
|
|
|
void
|
|
|
|
_Py_backtrace_symbols_fd(int fd, void *const *array, Py_ssize_t size)
|
|
|
|
{
|
|
|
|
VLA(Dl_info, info, size);
|
|
|
|
VLA(int, status, size);
|
|
|
|
/* Fill in the information we can get from dladdr() */
|
|
|
|
for (Py_ssize_t i = 0; i < size; ++i) {
|
2025-04-23 18:23:24 +01:00
|
|
|
#ifdef __APPLE__
|
|
|
|
status[i] = dladdr(array[i], &info[i]);
|
|
|
|
#else
|
2025-04-21 15:48:02 -04:00
|
|
|
struct link_map *map;
|
|
|
|
status[i] = dladdr1(array[i], &info[i], (void **)&map, RTLD_DL_LINKMAP);
|
|
|
|
if (status[i] != 0
|
|
|
|
&& info[i].dli_fname != NULL
|
|
|
|
&& info[i].dli_fname[0] != '\0') {
|
|
|
|
/* The load bias is more useful to the user than the load
|
|
|
|
address. The use of these addresses is to calculate an
|
|
|
|
address in the ELF file, so its prelinked bias is not
|
|
|
|
something we want to subtract out */
|
|
|
|
info[i].dli_fbase = (void *) map->l_addr;
|
|
|
|
}
|
2025-04-23 18:23:24 +01:00
|
|
|
#endif
|
2025-04-21 15:48:02 -04:00
|
|
|
}
|
|
|
|
for (Py_ssize_t i = 0; i < size; ++i) {
|
|
|
|
if (status[i] == 0
|
|
|
|
|| info[i].dli_fname == NULL
|
|
|
|
|| info[i].dli_fname[0] == '\0'
|
|
|
|
) {
|
2025-04-23 22:02:25 +02:00
|
|
|
PUTS(fd, " Binary file '<unknown>' [");
|
|
|
|
dump_pointer(fd, array[i]);
|
|
|
|
PUTS(fd, "]\n");
|
2025-04-21 15:48:02 -04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (info[i].dli_sname == NULL) {
|
|
|
|
/* We found no symbol name to use, so describe it as
|
|
|
|
relative to the file. */
|
|
|
|
info[i].dli_saddr = info[i].dli_fbase;
|
|
|
|
}
|
|
|
|
|
2025-04-23 22:02:25 +02:00
|
|
|
if (info[i].dli_sname == NULL && info[i].dli_saddr == 0) {
|
|
|
|
PUTS(fd, " Binary file \"");
|
|
|
|
PUTS(fd, info[i].dli_fname);
|
|
|
|
PUTS(fd, "\" [");
|
|
|
|
dump_pointer(fd, array[i]);
|
|
|
|
PUTS(fd, "]\n");
|
2025-04-21 15:48:02 -04:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
char sign;
|
|
|
|
ptrdiff_t offset;
|
|
|
|
if (array[i] >= (void *) info[i].dli_saddr) {
|
|
|
|
sign = '+';
|
|
|
|
offset = array[i] - info[i].dli_saddr;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sign = '-';
|
|
|
|
offset = info[i].dli_saddr - array[i];
|
|
|
|
}
|
|
|
|
const char *symbol_name = info[i].dli_sname != NULL ? info[i].dli_sname : "";
|
2025-04-23 22:02:25 +02:00
|
|
|
PUTS(fd, " Binary file \"");
|
|
|
|
PUTS(fd, info[i].dli_fname);
|
|
|
|
PUTS(fd, "\", at ");
|
|
|
|
PUTS(fd, symbol_name);
|
|
|
|
dump_char(fd, sign);
|
|
|
|
PUTS(fd, "0x");
|
|
|
|
dump_hexadecimal(fd, offset, sizeof(offset), 1);
|
|
|
|
PUTS(fd, " [");
|
|
|
|
dump_pointer(fd, array[i]);
|
|
|
|
PUTS(fd, "]\n");
|
2025-04-21 15:48:02 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
_Py_DumpStack(int fd)
|
|
|
|
{
|
|
|
|
#define BACKTRACE_SIZE 32
|
|
|
|
PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
|
|
|
|
VLA(void *, callstack, BACKTRACE_SIZE);
|
|
|
|
int frames = backtrace(callstack, BACKTRACE_SIZE);
|
|
|
|
if (frames == 0) {
|
|
|
|
// Some systems won't return anything for the stack trace
|
|
|
|
PUTS(fd, " <system returned no stack trace>\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
_Py_backtrace_symbols_fd(fd, callstack, frames);
|
|
|
|
if (frames == BACKTRACE_SIZE) {
|
|
|
|
PUTS(fd, " <truncated rest of calls>\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef BACKTRACE_SIZE
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
void
|
|
|
|
_Py_DumpStack(int fd)
|
|
|
|
{
|
|
|
|
PUTS(fd, "Current thread's C stack trace (most recent call first):\n");
|
|
|
|
PUTS(fd, " <cannot get C stack on this system>\n");
|
|
|
|
}
|
|
|
|
#endif
|