summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-11-06 18:09:22 (GMT)
committerGitHub <noreply@github.com>2023-11-06 18:09:22 (GMT)
commitd4426e8d001cfb4590911e2e7de6963e12529faf (patch)
treee8363d3f93fd0bc6d86996603971081507e97ec4
parent836e0a75d565ecb7e2485fee88dbe67e649a1d5f (diff)
downloadcpython-d4426e8d001cfb4590911e2e7de6963e12529faf.zip
cpython-d4426e8d001cfb4590911e2e7de6963e12529faf.tar.gz
cpython-d4426e8d001cfb4590911e2e7de6963e12529faf.tar.bz2
gh-76785: Move _Py_excinfo Functions Out of the Internal C-API (gh-111715)
I added _Py_excinfo to the internal API (and added its functions in Python/errors.c) in gh-111530 (9322ce9). Since then I've had a nagging sense that I should have added the type and functions in its own PR. While I do plan on using _Py_excinfo outside crossinterp.c very soon (see gh-111572/gh-111573), I'd still feel more comfortable if the _Py_excinfo stuff went in as its own PR. Hence, here we are. (FWIW, I may combine that with gh-111572, which I may, in turn, combine with gh-111573. We'll see.)
-rw-r--r--Include/internal/pycore_crossinterp.h11
-rw-r--r--Include/internal/pycore_pyerrors.h24
-rw-r--r--Python/crossinterp.c123
-rw-r--r--Python/errors.c175
4 files changed, 134 insertions, 199 deletions
diff --git a/Include/internal/pycore_crossinterp.h b/Include/internal/pycore_crossinterp.h
index 9600dfb..ee9ff00 100644
--- a/Include/internal/pycore_crossinterp.h
+++ b/Include/internal/pycore_crossinterp.h
@@ -164,6 +164,17 @@ extern void _PyXI_Fini(PyInterpreterState *interp);
/* short-term data sharing */
/***************************/
+// Ultimately we'd like to preserve enough information about the
+// exception and traceback that we could re-constitute (or at least
+// simulate, a la traceback.TracebackException), and even chain, a copy
+// of the exception in the calling interpreter.
+
+typedef struct _excinfo {
+ const char *type;
+ const char *msg;
+} _Py_excinfo;
+
+
typedef enum error_code {
_PyXI_ERR_NO_ERROR = 0,
_PyXI_ERR_UNCAUGHT_EXCEPTION = -1,
diff --git a/Include/internal/pycore_pyerrors.h b/Include/internal/pycore_pyerrors.h
index a953d2b..0f16fb8 100644
--- a/Include/internal/pycore_pyerrors.h
+++ b/Include/internal/pycore_pyerrors.h
@@ -68,30 +68,6 @@ extern PyStatus _PyErr_InitTypes(PyInterpreterState *);
extern void _PyErr_FiniTypes(PyInterpreterState *);
-/* exception snapshots */
-
-// Ultimately we'd like to preserve enough information about the
-// exception and traceback that we could re-constitute (or at least
-// simulate, a la traceback.TracebackException), and even chain, a copy
-// of the exception in the calling interpreter.
-
-typedef struct _excinfo {
- const char *type;
- const char *msg;
-} _Py_excinfo;
-
-extern void _Py_excinfo_Clear(_Py_excinfo *info);
-extern int _Py_excinfo_Copy(_Py_excinfo *dest, _Py_excinfo *src);
-extern const char * _Py_excinfo_InitFromException(
- _Py_excinfo *info,
- PyObject *exc);
-extern void _Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype);
-extern const char * _Py_excinfo_AsUTF8(
- _Py_excinfo *info,
- char *buf,
- size_t bufsize);
-
-
/* other API */
static inline PyObject* _PyErr_Occurred(PyThreadState *tstate)
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index a65355a..de28cb7 100644
--- a/Python/crossinterp.c
+++ b/Python/crossinterp.c
@@ -801,6 +801,17 @@ _xidregistry_fini(struct _xidregistry *registry)
/*************************/
static const char *
+_copy_raw_string(const char *str)
+{
+ char *copied = PyMem_RawMalloc(strlen(str)+1);
+ if (copied == NULL) {
+ return NULL;
+ }
+ strcpy(copied, str);
+ return copied;
+}
+
+static const char *
_copy_string_obj_raw(PyObject *strobj)
{
const char *str = PyUnicode_AsUTF8(strobj);
@@ -835,6 +846,118 @@ _release_xid_data(_PyCrossInterpreterData *data, int rawfree)
}
+/* exception snapshots */
+
+static int
+_exc_type_name_as_utf8(PyObject *exc, const char **p_typename)
+{
+ // XXX Use PyObject_GetAttrString(Py_TYPE(exc), '__name__')?
+ PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
+ if (nameobj == NULL) {
+ assert(PyErr_Occurred());
+ *p_typename = "unable to format exception type name";
+ return -1;
+ }
+ const char *name = PyUnicode_AsUTF8(nameobj);
+ if (name == NULL) {
+ assert(PyErr_Occurred());
+ Py_DECREF(nameobj);
+ *p_typename = "unable to encode exception type name";
+ return -1;
+ }
+ name = _copy_raw_string(name);
+ Py_DECREF(nameobj);
+ if (name == NULL) {
+ *p_typename = "out of memory copying exception type name";
+ return -1;
+ }
+ *p_typename = name;
+ return 0;
+}
+
+static int
+_exc_msg_as_utf8(PyObject *exc, const char **p_msg)
+{
+ PyObject *msgobj = PyObject_Str(exc);
+ if (msgobj == NULL) {
+ assert(PyErr_Occurred());
+ *p_msg = "unable to format exception message";
+ return -1;
+ }
+ const char *msg = PyUnicode_AsUTF8(msgobj);
+ if (msg == NULL) {
+ assert(PyErr_Occurred());
+ Py_DECREF(msgobj);
+ *p_msg = "unable to encode exception message";
+ return -1;
+ }
+ msg = _copy_raw_string(msg);
+ Py_DECREF(msgobj);
+ if (msg == NULL) {
+ assert(PyErr_ExceptionMatches(PyExc_MemoryError));
+ *p_msg = "out of memory copying exception message";
+ return -1;
+ }
+ *p_msg = msg;
+ return 0;
+}
+
+static void
+_Py_excinfo_Clear(_Py_excinfo *info)
+{
+ if (info->type != NULL) {
+ PyMem_RawFree((void *)info->type);
+ }
+ if (info->msg != NULL) {
+ PyMem_RawFree((void *)info->msg);
+ }
+ *info = (_Py_excinfo){ NULL };
+}
+
+static const char *
+_Py_excinfo_InitFromException(_Py_excinfo *info, PyObject *exc)
+{
+ assert(exc != NULL);
+
+ // Extract the exception type name.
+ const char *typename = NULL;
+ if (_exc_type_name_as_utf8(exc, &typename) < 0) {
+ assert(typename != NULL);
+ return typename;
+ }
+
+ // Extract the exception message.
+ const char *msg = NULL;
+ if (_exc_msg_as_utf8(exc, &msg) < 0) {
+ assert(msg != NULL);
+ return msg;
+ }
+
+ info->type = typename;
+ info->msg = msg;
+ return NULL;
+}
+
+static void
+_Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype)
+{
+ if (info->type != NULL) {
+ if (info->msg != NULL) {
+ PyErr_Format(exctype, "%s: %s", info->type, info->msg);
+ }
+ else {
+ PyErr_SetString(exctype, info->type);
+ }
+ }
+ else if (info->msg != NULL) {
+ PyErr_SetString(exctype, info->msg);
+ }
+ else {
+ PyErr_SetNone(exctype);
+ }
+}
+
+
/***************************/
/* short-term data sharing */
/***************************/
diff --git a/Python/errors.c b/Python/errors.c
index c55ebfd..ed5eec5 100644
--- a/Python/errors.c
+++ b/Python/errors.c
@@ -1934,178 +1934,3 @@ PyErr_ProgramTextObject(PyObject *filename, int lineno)
{
return _PyErr_ProgramDecodedTextObject(filename, lineno, NULL);
}
-
-
-/***********************/
-/* exception snapshots */
-/***********************/
-
-static const char *
-_copy_raw_string(const char *str)
-{
- char *copied = PyMem_RawMalloc(strlen(str)+1);
- if (copied == NULL) {
- return NULL;
- }
- strcpy(copied, str);
- return copied;
-}
-
-static int
-_exc_type_name_as_utf8(PyObject *exc, const char **p_typename)
-{
- // XXX Use PyObject_GetAttrString(Py_TYPE(exc), '__name__')?
- PyObject *nameobj = PyUnicode_FromString(Py_TYPE(exc)->tp_name);
- if (nameobj == NULL) {
- assert(PyErr_Occurred());
- *p_typename = "unable to format exception type name";
- return -1;
- }
- const char *name = PyUnicode_AsUTF8(nameobj);
- if (name == NULL) {
- assert(PyErr_Occurred());
- Py_DECREF(nameobj);
- *p_typename = "unable to encode exception type name";
- return -1;
- }
- name = _copy_raw_string(name);
- Py_DECREF(nameobj);
- if (name == NULL) {
- *p_typename = "out of memory copying exception type name";
- return -1;
- }
- *p_typename = name;
- return 0;
-}
-
-static int
-_exc_msg_as_utf8(PyObject *exc, const char **p_msg)
-{
- PyObject *msgobj = PyObject_Str(exc);
- if (msgobj == NULL) {
- assert(PyErr_Occurred());
- *p_msg = "unable to format exception message";
- return -1;
- }
- const char *msg = PyUnicode_AsUTF8(msgobj);
- if (msg == NULL) {
- assert(PyErr_Occurred());
- Py_DECREF(msgobj);
- *p_msg = "unable to encode exception message";
- return -1;
- }
- msg = _copy_raw_string(msg);
- Py_DECREF(msgobj);
- if (msg == NULL) {
- assert(PyErr_ExceptionMatches(PyExc_MemoryError));
- *p_msg = "out of memory copying exception message";
- return -1;
- }
- *p_msg = msg;
- return 0;
-}
-
-void
-_Py_excinfo_Clear(_Py_excinfo *info)
-{
- if (info->type != NULL) {
- PyMem_RawFree((void *)info->type);
- }
- if (info->msg != NULL) {
- PyMem_RawFree((void *)info->msg);
- }
- *info = (_Py_excinfo){ NULL };
-}
-
-int
-_Py_excinfo_Copy(_Py_excinfo *dest, _Py_excinfo *src)
-{
- // XXX Clear dest first?
-
- if (src->type == NULL) {
- dest->type = NULL;
- }
- else {
- dest->type = _copy_raw_string(src->type);
- if (dest->type == NULL) {
- return -1;
- }
- }
-
- if (src->msg == NULL) {
- dest->msg = NULL;
- }
- else {
- dest->msg = _copy_raw_string(src->msg);
- if (dest->msg == NULL) {
- return -1;
- }
- }
-
- return 0;
-}
-
-const char *
-_Py_excinfo_InitFromException(_Py_excinfo *info, PyObject *exc)
-{
- assert(exc != NULL);
-
- // Extract the exception type name.
- const char *typename = NULL;
- if (_exc_type_name_as_utf8(exc, &typename) < 0) {
- assert(typename != NULL);
- return typename;
- }
-
- // Extract the exception message.
- const char *msg = NULL;
- if (_exc_msg_as_utf8(exc, &msg) < 0) {
- assert(msg != NULL);
- return msg;
- }
-
- info->type = typename;
- info->msg = msg;
- return NULL;
-}
-
-void
-_Py_excinfo_Apply(_Py_excinfo *info, PyObject *exctype)
-{
- if (info->type != NULL) {
- if (info->msg != NULL) {
- PyErr_Format(exctype, "%s: %s", info->type, info->msg);
- }
- else {
- PyErr_SetString(exctype, info->type);
- }
- }
- else if (info->msg != NULL) {
- PyErr_SetString(exctype, info->msg);
- }
- else {
- PyErr_SetNone(exctype);
- }
-}
-
-const char *
-_Py_excinfo_AsUTF8(_Py_excinfo *info, char *buf, size_t bufsize)
-{
- // XXX Dynamically allocate if no buf provided?
- assert(buf != NULL);
- if (info->type != NULL) {
- if (info->msg != NULL) {
- snprintf(buf, bufsize, "%s: %s", info->type, info->msg);
- return buf;
- }
- else {
- return info->type;
- }
- }
- else if (info->msg != NULL) {
- return info->msg;
- }
- else {
- return NULL;
- }
-}