aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Python/crossinterp.c
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2023-11-06 11:09:22 -0700
committerGitHub <noreply@github.com>2023-11-06 11:09:22 -0700
commitd4426e8d001cfb4590911e2e7de6963e12529faf (patch)
treee8363d3f93fd0bc6d86996603971081507e97ec4 /Python/crossinterp.c
parent836e0a75d565ecb7e2485fee88dbe67e649a1d5f (diff)
downloadcpython-d4426e8d001cfb4590911e2e7de6963e12529faf.tar.gz
cpython-d4426e8d001cfb4590911e2e7de6963e12529faf.zip
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.)
Diffstat (limited to 'Python/crossinterp.c')
-rw-r--r--Python/crossinterp.c123
1 files changed, 123 insertions, 0 deletions
diff --git a/Python/crossinterp.c b/Python/crossinterp.c
index a65355a49c5..de28cb70717 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 */
/***************************/