mirror of https://github.com/python/cpython.git
gh-132781: Cleanup Code Related to NotShareableError (gh-132782)
The following are added to the internal C-API: * _PyErr_FormatV() * _PyErr_SetModuleNotFoundError() * _PyXIData_GetNotShareableErrorType() * _PyXIData_FormatNotShareableError() We also drop _PyXIData_lookup_context_t and _PyXIData_GetLookupContext().
This commit is contained in:
parent
4c20f46fa0
commit
cd9536a087
|
@ -97,26 +97,22 @@ PyAPI_FUNC(void) _PyXIData_Free(_PyXIData_t *data);
|
||||||
|
|
||||||
typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);
|
typedef int (*xidatafunc)(PyThreadState *tstate, PyObject *, _PyXIData_t *);
|
||||||
|
|
||||||
typedef struct _xid_lookup_state _PyXIData_lookup_t;
|
PyAPI_FUNC(PyObject *) _PyXIData_GetNotShareableErrorType(PyThreadState *);
|
||||||
|
PyAPI_FUNC(void) _PyXIData_SetNotShareableError(PyThreadState *, const char *);
|
||||||
typedef struct {
|
PyAPI_FUNC(void) _PyXIData_FormatNotShareableError(
|
||||||
_PyXIData_lookup_t *global;
|
PyThreadState *,
|
||||||
_PyXIData_lookup_t *local;
|
const char *,
|
||||||
PyObject *PyExc_NotShareableError;
|
...);
|
||||||
} _PyXIData_lookup_context_t;
|
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyXIData_GetLookupContext(
|
|
||||||
PyInterpreterState *,
|
|
||||||
_PyXIData_lookup_context_t *);
|
|
||||||
|
|
||||||
PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(
|
PyAPI_FUNC(xidatafunc) _PyXIData_Lookup(
|
||||||
_PyXIData_lookup_context_t *,
|
PyThreadState *,
|
||||||
PyObject *);
|
PyObject *);
|
||||||
PyAPI_FUNC(int) _PyObject_CheckXIData(
|
PyAPI_FUNC(int) _PyObject_CheckXIData(
|
||||||
_PyXIData_lookup_context_t *,
|
PyThreadState *,
|
||||||
PyObject *);
|
PyObject *);
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyObject_GetXIData(
|
PyAPI_FUNC(int) _PyObject_GetXIData(
|
||||||
_PyXIData_lookup_context_t *,
|
PyThreadState *,
|
||||||
PyObject *,
|
PyObject *,
|
||||||
_PyXIData_t *);
|
_PyXIData_t *);
|
||||||
|
|
||||||
|
@ -171,6 +167,8 @@ PyAPI_FUNC(void) _PyXIData_Clear( PyInterpreterState *, _PyXIData_t *);
|
||||||
/* runtime state & lifecycle */
|
/* runtime state & lifecycle */
|
||||||
/*****************************/
|
/*****************************/
|
||||||
|
|
||||||
|
typedef struct _xid_lookup_state _PyXIData_lookup_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// builtin types
|
// builtin types
|
||||||
_PyXIData_lookup_t data_lookup;
|
_PyXIData_lookup_t data_lookup;
|
||||||
|
|
|
@ -28,11 +28,11 @@ typedef struct {
|
||||||
} _PyXIData_registry_t;
|
} _PyXIData_registry_t;
|
||||||
|
|
||||||
PyAPI_FUNC(int) _PyXIData_RegisterClass(
|
PyAPI_FUNC(int) _PyXIData_RegisterClass(
|
||||||
_PyXIData_lookup_context_t *,
|
PyThreadState *,
|
||||||
PyTypeObject *,
|
PyTypeObject *,
|
||||||
xidatafunc);
|
xidatafunc);
|
||||||
PyAPI_FUNC(int) _PyXIData_UnregisterClass(
|
PyAPI_FUNC(int) _PyXIData_UnregisterClass(
|
||||||
_PyXIData_lookup_context_t *,
|
PyThreadState *,
|
||||||
PyTypeObject *);
|
PyTypeObject *);
|
||||||
|
|
||||||
struct _xid_lookup_state {
|
struct _xid_lookup_state {
|
||||||
|
|
|
@ -60,6 +60,7 @@ extern PyObject* _PyErr_SetImportErrorWithNameFrom(
|
||||||
PyObject *,
|
PyObject *,
|
||||||
PyObject *,
|
PyObject *,
|
||||||
PyObject *);
|
PyObject *);
|
||||||
|
extern int _PyErr_SetModuleNotFoundError(PyObject *name);
|
||||||
|
|
||||||
|
|
||||||
/* runtime lifecycle */
|
/* runtime lifecycle */
|
||||||
|
@ -113,6 +114,7 @@ extern void _PyErr_SetObject(
|
||||||
PyObject *value);
|
PyObject *value);
|
||||||
|
|
||||||
extern void _PyErr_ChainStackItem(void);
|
extern void _PyErr_ChainStackItem(void);
|
||||||
|
extern void _PyErr_ChainExceptions1Tstate(PyThreadState *, PyObject *);
|
||||||
|
|
||||||
PyAPI_FUNC(void) _PyErr_Clear(PyThreadState *tstate);
|
PyAPI_FUNC(void) _PyErr_Clear(PyThreadState *tstate);
|
||||||
|
|
||||||
|
@ -148,6 +150,12 @@ PyAPI_FUNC(PyObject*) _PyErr_Format(
|
||||||
const char *format,
|
const char *format,
|
||||||
...);
|
...);
|
||||||
|
|
||||||
|
PyAPI_FUNC(PyObject*) _PyErr_FormatV(
|
||||||
|
PyThreadState *tstate,
|
||||||
|
PyObject *exception,
|
||||||
|
const char *format,
|
||||||
|
va_list vargs);
|
||||||
|
|
||||||
extern void _PyErr_NormalizeException(
|
extern void _PyErr_NormalizeException(
|
||||||
PyThreadState *tstate,
|
PyThreadState *tstate,
|
||||||
PyObject **exc,
|
PyObject **exc,
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
_interpreters = import_helper.import_module('_interpreters')
|
_interpreters = import_helper.import_module('_interpreters')
|
||||||
_testinternalcapi = import_helper.import_module('_testinternalcapi')
|
_testinternalcapi = import_helper.import_module('_testinternalcapi')
|
||||||
from _interpreters import InterpreterNotFoundError
|
from _interpreters import InterpreterNotFoundError, NotShareableError
|
||||||
|
|
||||||
|
|
||||||
##################################
|
##################################
|
||||||
|
@ -189,8 +189,9 @@ def test_non_shareable_int(self):
|
||||||
]
|
]
|
||||||
for i in ints:
|
for i in ints:
|
||||||
with self.subTest(i):
|
with self.subTest(i):
|
||||||
with self.assertRaises(OverflowError):
|
with self.assertRaises(NotShareableError) as cm:
|
||||||
_testinternalcapi.get_crossinterp_data(i)
|
_testinternalcapi.get_crossinterp_data(i)
|
||||||
|
self.assertIsInstance(cm.exception.__cause__, OverflowError)
|
||||||
|
|
||||||
def test_bool(self):
|
def test_bool(self):
|
||||||
self._assert_values([True, False])
|
self._assert_values([True, False])
|
||||||
|
@ -215,14 +216,12 @@ def test_tuples_containing_non_shareable_types(self):
|
||||||
for s in non_shareables:
|
for s in non_shareables:
|
||||||
value = tuple([0, 1.0, s])
|
value = tuple([0, 1.0, s])
|
||||||
with self.subTest(repr(value)):
|
with self.subTest(repr(value)):
|
||||||
# XXX Assert the NotShareableError when it is exported
|
with self.assertRaises(NotShareableError):
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
_testinternalcapi.get_crossinterp_data(value)
|
_testinternalcapi.get_crossinterp_data(value)
|
||||||
# Check nested as well
|
# Check nested as well
|
||||||
value = tuple([0, 1., (s,)])
|
value = tuple([0, 1., (s,)])
|
||||||
with self.subTest("nested " + repr(value)):
|
with self.subTest("nested " + repr(value)):
|
||||||
# XXX Assert the NotShareableError when it is exported
|
with self.assertRaises(NotShareableError):
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
_testinternalcapi.get_crossinterp_data(value)
|
_testinternalcapi.get_crossinterp_data(value)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -693,8 +693,7 @@ def test_dict_and_kwargs(self):
|
||||||
|
|
||||||
def test_not_shareable(self):
|
def test_not_shareable(self):
|
||||||
interp = interpreters.create()
|
interp = interpreters.create()
|
||||||
# XXX TypeError?
|
with self.assertRaises(interpreters.NotShareableError):
|
||||||
with self.assertRaises(ValueError):
|
|
||||||
interp.prepare_main(spam={'spam': 'eggs', 'foo': 'bar'})
|
interp.prepare_main(spam={'spam': 'eggs', 'foo': 'bar'})
|
||||||
|
|
||||||
# Make sure neither was actually bound.
|
# Make sure neither was actually bound.
|
||||||
|
|
|
@ -1754,17 +1754,10 @@ static int
|
||||||
channel_send(_channels *channels, int64_t cid, PyObject *obj,
|
channel_send(_channels *channels, int64_t cid, PyObject *obj,
|
||||||
_waiting_t *waiting, int unboundop)
|
_waiting_t *waiting, int unboundop)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = _get_current_interp();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
if (interp == NULL) {
|
PyInterpreterState *interp = tstate->interp;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
int64_t interpid = PyInterpreterState_GetID(interp);
|
int64_t interpid = PyInterpreterState_GetID(interp);
|
||||||
|
|
||||||
_PyXIData_lookup_context_t ctx;
|
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up the channel.
|
// Look up the channel.
|
||||||
PyThread_type_lock mutex = NULL;
|
PyThread_type_lock mutex = NULL;
|
||||||
_channel_state *chan = NULL;
|
_channel_state *chan = NULL;
|
||||||
|
@ -1786,7 +1779,7 @@ channel_send(_channels *channels, int64_t cid, PyObject *obj,
|
||||||
PyThread_release_lock(mutex);
|
PyThread_release_lock(mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
|
if (_PyObject_GetXIData(tstate, obj, data) != 0) {
|
||||||
PyThread_release_lock(mutex);
|
PyThread_release_lock(mutex);
|
||||||
GLOBAL_FREE(data);
|
GLOBAL_FREE(data);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -1127,11 +1127,7 @@ queue_destroy(_queues *queues, int64_t qid)
|
||||||
static int
|
static int
|
||||||
queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
|
queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
_PyXIData_lookup_context_t ctx;
|
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up the queue.
|
// Look up the queue.
|
||||||
_queue *queue = NULL;
|
_queue *queue = NULL;
|
||||||
|
@ -1147,12 +1143,13 @@ queue_put(_queues *queues, int64_t qid, PyObject *obj, int fmt, int unboundop)
|
||||||
_queue_unmark_waiter(queue, queues->mutex);
|
_queue_unmark_waiter(queue, queues->mutex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
|
if (_PyObject_GetXIData(tstate, obj, data) != 0) {
|
||||||
_queue_unmark_waiter(queue, queues->mutex);
|
_queue_unmark_waiter(queue, queues->mutex);
|
||||||
GLOBAL_FREE(data);
|
GLOBAL_FREE(data);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
assert(_PyXIData_INTERPID(data) == PyInterpreterState_GetID(interp));
|
assert(_PyXIData_INTERPID(data) ==
|
||||||
|
PyInterpreterState_GetID(tstate->interp));
|
||||||
|
|
||||||
// Add the data to the queue.
|
// Add the data to the queue.
|
||||||
int64_t interpid = -1; // _queueitem_init() will set it.
|
int64_t interpid = -1; // _queueitem_init() will set it.
|
||||||
|
|
|
@ -8,24 +8,16 @@
|
||||||
static int
|
static int
|
||||||
ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
|
ensure_xid_class(PyTypeObject *cls, xidatafunc getdata)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
_PyXIData_lookup_context_t ctx;
|
return _PyXIData_RegisterClass(tstate, cls, getdata);
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return _PyXIData_RegisterClass(&ctx, cls, getdata);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef REGISTERS_HEAP_TYPES
|
#ifdef REGISTERS_HEAP_TYPES
|
||||||
static int
|
static int
|
||||||
clear_xid_class(PyTypeObject *cls)
|
clear_xid_class(PyTypeObject *cls)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
_PyXIData_lookup_context_t ctx;
|
return _PyXIData_UnregisterClass(tstate, cls);
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return _PyXIData_UnregisterClass(&ctx, cls);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1278,13 +1278,8 @@ object_is_shareable(PyObject *self, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
_PyXIData_lookup_context_t ctx;
|
if (_PyObject_CheckXIData(tstate, obj) == 0) {
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_PyObject_CheckXIData(&ctx, obj) == 0) {
|
|
||||||
Py_RETURN_TRUE;
|
Py_RETURN_TRUE;
|
||||||
}
|
}
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
|
@ -1577,14 +1572,9 @@ The 'interpreters' module provides a more convenient interface.");
|
||||||
static int
|
static int
|
||||||
module_exec(PyObject *mod)
|
module_exec(PyObject *mod)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
module_state *state = get_module_state(mod);
|
module_state *state = get_module_state(mod);
|
||||||
|
|
||||||
_PyXIData_lookup_context_t ctx;
|
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ADD_WHENCE(NAME) \
|
#define ADD_WHENCE(NAME) \
|
||||||
if (PyModule_AddIntConstant(mod, "WHENCE_" #NAME, \
|
if (PyModule_AddIntConstant(mod, "WHENCE_" #NAME, \
|
||||||
_PyInterpreterState_WHENCE_##NAME) < 0) \
|
_PyInterpreterState_WHENCE_##NAME) < 0) \
|
||||||
|
@ -1606,7 +1596,8 @@ module_exec(PyObject *mod)
|
||||||
if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterNotFoundError) < 0) {
|
if (PyModule_AddType(mod, (PyTypeObject *)PyExc_InterpreterNotFoundError) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if (PyModule_AddType(mod, (PyTypeObject *)ctx.PyExc_NotShareableError) < 0) {
|
PyObject *exctype = _PyXIData_GetNotShareableErrorType(tstate);
|
||||||
|
if (PyModule_AddType(mod, (PyTypeObject *)exctype) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1696,11 +1696,7 @@ _xid_capsule_destructor(PyObject *capsule)
|
||||||
static PyObject *
|
static PyObject *
|
||||||
get_crossinterp_data(PyObject *self, PyObject *args)
|
get_crossinterp_data(PyObject *self, PyObject *args)
|
||||||
{
|
{
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
_PyXIData_lookup_context_t ctx;
|
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
PyObject *obj = NULL;
|
PyObject *obj = NULL;
|
||||||
if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) {
|
if (!PyArg_ParseTuple(args, "O:get_crossinterp_data", &obj)) {
|
||||||
|
@ -1711,7 +1707,7 @@ get_crossinterp_data(PyObject *self, PyObject *args)
|
||||||
if (data == NULL) {
|
if (data == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (_PyObject_GetXIData(&ctx, obj, data) != 0) {
|
if (_PyObject_GetXIData(tstate, obj, data) != 0) {
|
||||||
_PyXIData_Free(data);
|
_PyXIData_Free(data);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,8 @@ _Py_CallInInterpreterAndRawFree(PyInterpreterState *interp,
|
||||||
|
|
||||||
static void xid_lookup_init(_PyXIData_lookup_t *);
|
static void xid_lookup_init(_PyXIData_lookup_t *);
|
||||||
static void xid_lookup_fini(_PyXIData_lookup_t *);
|
static void xid_lookup_fini(_PyXIData_lookup_t *);
|
||||||
static xidatafunc lookup_getdata(_PyXIData_lookup_context_t *, PyObject *);
|
struct _dlcontext;
|
||||||
|
static xidatafunc lookup_getdata(struct _dlcontext *, PyObject *);
|
||||||
#include "crossinterp_data_lookup.h"
|
#include "crossinterp_data_lookup.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -198,31 +199,34 @@ _check_xidata(PyThreadState *tstate, _PyXIData_t *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
_set_xid_lookup_failure(dlcontext_t *ctx, PyObject *obj, const char *msg)
|
_set_xid_lookup_failure(PyThreadState *tstate, PyObject *obj, const char *msg,
|
||||||
|
PyObject *cause)
|
||||||
{
|
{
|
||||||
PyObject *exctype = ctx->PyExc_NotShareableError;
|
|
||||||
assert(exctype != NULL);
|
|
||||||
if (msg != NULL) {
|
if (msg != NULL) {
|
||||||
assert(obj == NULL);
|
assert(obj == NULL);
|
||||||
PyErr_SetString(exctype, msg);
|
set_notshareableerror(tstate, cause, 0, msg);
|
||||||
}
|
}
|
||||||
else if (obj == NULL) {
|
else if (obj == NULL) {
|
||||||
PyErr_SetString(exctype,
|
msg = "object does not support cross-interpreter data";
|
||||||
"object does not support cross-interpreter data");
|
set_notshareableerror(tstate, cause, 0, msg);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
PyErr_Format(exctype,
|
msg = "%S does not support cross-interpreter data";
|
||||||
"%S does not support cross-interpreter data", obj);
|
format_notshareableerror(tstate, cause, 0, msg, obj);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyObject_CheckXIData(_PyXIData_lookup_context_t *ctx, PyObject *obj)
|
_PyObject_CheckXIData(PyThreadState *tstate, PyObject *obj)
|
||||||
{
|
{
|
||||||
xidatafunc getdata = lookup_getdata(ctx, obj);
|
dlcontext_t ctx;
|
||||||
|
if (get_lookup_context(tstate, &ctx) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
xidatafunc getdata = lookup_getdata(&ctx, obj);
|
||||||
if (getdata == NULL) {
|
if (getdata == NULL) {
|
||||||
if (!PyErr_Occurred()) {
|
if (!_PyErr_Occurred(tstate)) {
|
||||||
_set_xid_lookup_failure(ctx, obj, NULL);
|
_set_xid_lookup_failure(tstate, obj, NULL, NULL);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -230,10 +234,9 @@ _PyObject_CheckXIData(_PyXIData_lookup_context_t *ctx, PyObject *obj)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyObject_GetXIData(_PyXIData_lookup_context_t *ctx,
|
_PyObject_GetXIData(PyThreadState *tstate,
|
||||||
PyObject *obj, _PyXIData_t *data)
|
PyObject *obj, _PyXIData_t *data)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = PyThreadState_Get();
|
|
||||||
PyInterpreterState *interp = tstate->interp;
|
PyInterpreterState *interp = tstate->interp;
|
||||||
|
|
||||||
// Reset data before re-populating.
|
// Reset data before re-populating.
|
||||||
|
@ -241,18 +244,26 @@ _PyObject_GetXIData(_PyXIData_lookup_context_t *ctx,
|
||||||
_PyXIData_INTERPID(data) = -1;
|
_PyXIData_INTERPID(data) = -1;
|
||||||
|
|
||||||
// Call the "getdata" func for the object.
|
// Call the "getdata" func for the object.
|
||||||
|
dlcontext_t ctx;
|
||||||
|
if (get_lookup_context(tstate, &ctx) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
Py_INCREF(obj);
|
Py_INCREF(obj);
|
||||||
xidatafunc getdata = lookup_getdata(ctx, obj);
|
xidatafunc getdata = lookup_getdata(&ctx, obj);
|
||||||
if (getdata == NULL) {
|
if (getdata == NULL) {
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
if (!PyErr_Occurred()) {
|
if (!_PyErr_Occurred(tstate)) {
|
||||||
_set_xid_lookup_failure(ctx, obj, NULL);
|
_set_xid_lookup_failure(tstate, obj, NULL, NULL);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
int res = getdata(tstate, obj, data);
|
int res = getdata(tstate, obj, data);
|
||||||
Py_DECREF(obj);
|
Py_DECREF(obj);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
|
PyObject *cause = _PyErr_GetRaisedException(tstate);
|
||||||
|
assert(cause != NULL);
|
||||||
|
_set_xid_lookup_failure(tstate, obj, NULL, cause);
|
||||||
|
Py_XDECREF(cause);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +977,7 @@ _PyXI_ClearExcInfo(_PyXI_excinfo *info)
|
||||||
static int
|
static int
|
||||||
_PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
|
_PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
|
||||||
{
|
{
|
||||||
dlcontext_t ctx;
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
|
||||||
assert(!PyErr_Occurred());
|
assert(!PyErr_Occurred());
|
||||||
switch (code) {
|
switch (code) {
|
||||||
|
@ -997,10 +1008,7 @@ _PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
|
||||||
"failed to apply namespace to __main__");
|
"failed to apply namespace to __main__");
|
||||||
break;
|
break;
|
||||||
case _PyXI_ERR_NOT_SHAREABLE:
|
case _PyXI_ERR_NOT_SHAREABLE:
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
_set_xid_lookup_failure(tstate, NULL, NULL, NULL);
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
_set_xid_lookup_failure(&ctx, NULL, NULL);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
#ifdef Py_DEBUG
|
#ifdef Py_DEBUG
|
||||||
|
@ -1056,17 +1064,15 @@ _PyXI_InitError(_PyXI_error *error, PyObject *excobj, _PyXI_errcode code)
|
||||||
PyObject *
|
PyObject *
|
||||||
_PyXI_ApplyError(_PyXI_error *error)
|
_PyXI_ApplyError(_PyXI_error *error)
|
||||||
{
|
{
|
||||||
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
if (error->code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
|
if (error->code == _PyXI_ERR_UNCAUGHT_EXCEPTION) {
|
||||||
// Raise an exception that proxies the propagated exception.
|
// Raise an exception that proxies the propagated exception.
|
||||||
return _PyXI_excinfo_AsObject(&error->uncaught);
|
return _PyXI_excinfo_AsObject(&error->uncaught);
|
||||||
}
|
}
|
||||||
else if (error->code == _PyXI_ERR_NOT_SHAREABLE) {
|
else if (error->code == _PyXI_ERR_NOT_SHAREABLE) {
|
||||||
// Propagate the exception directly.
|
// Propagate the exception directly.
|
||||||
dlcontext_t ctx;
|
assert(!_PyErr_Occurred(tstate));
|
||||||
if (_PyXIData_GetLookupContext(error->interp, &ctx) < 0) {
|
_set_xid_lookup_failure(tstate, NULL, error->uncaught.msg, NULL);
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
_set_xid_lookup_failure(&ctx, NULL, error->uncaught.msg);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Raise an exception corresponding to the code.
|
// Raise an exception corresponding to the code.
|
||||||
|
@ -1153,12 +1159,8 @@ _sharednsitem_set_value(_PyXI_namespace_item *item, PyObject *value)
|
||||||
PyErr_NoMemory();
|
PyErr_NoMemory();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
dlcontext_t ctx;
|
if (_PyObject_GetXIData(tstate, value, item->data) != 0) {
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (_PyObject_GetXIData(&ctx, value, item->data) != 0) {
|
|
||||||
PyMem_RawFree(item->data);
|
PyMem_RawFree(item->data);
|
||||||
item->data = NULL;
|
item->data = NULL;
|
||||||
// The caller may want to propagate PyExc_NotShareableError
|
// The caller may want to propagate PyExc_NotShareableError
|
||||||
|
@ -1615,14 +1617,14 @@ _propagate_not_shareable_error(_PyXI_session *session)
|
||||||
if (session == NULL) {
|
if (session == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyInterpreterState *interp = PyInterpreterState_Get();
|
PyThreadState *tstate = PyThreadState_Get();
|
||||||
dlcontext_t ctx;
|
PyObject *exctype = get_notshareableerror_type(tstate);
|
||||||
if (_PyXIData_GetLookupContext(interp, &ctx) < 0) {
|
if (exctype == NULL) {
|
||||||
PyErr_FormatUnraisable(
|
PyErr_FormatUnraisable(
|
||||||
"Exception ignored while propagating not shareable error");
|
"Exception ignored while propagating not shareable error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (PyErr_ExceptionMatches(ctx.PyExc_NotShareableError)) {
|
if (PyErr_ExceptionMatches(exctype)) {
|
||||||
// We want to propagate the exception directly.
|
// We want to propagate the exception directly.
|
||||||
session->_error_override = _PyXI_ERR_NOT_SHAREABLE;
|
session->_error_override = _PyXI_ERR_NOT_SHAREABLE;
|
||||||
session->error_override = &session->_error_override;
|
session->error_override = &session->_error_override;
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
|
#include "pycore_weakref.h" // _PyWeakref_GET_REF()
|
||||||
|
|
||||||
|
|
||||||
typedef _PyXIData_lookup_context_t dlcontext_t;
|
typedef struct _dlcontext {
|
||||||
|
_PyXIData_lookup_t *global;
|
||||||
|
_PyXIData_lookup_t *local;
|
||||||
|
} dlcontext_t;
|
||||||
typedef _PyXIData_registry_t dlregistry_t;
|
typedef _PyXIData_registry_t dlregistry_t;
|
||||||
typedef _PyXIData_regitem_t dlregitem_t;
|
typedef _PyXIData_regitem_t dlregitem_t;
|
||||||
|
|
||||||
|
@ -26,6 +29,26 @@ xid_lookup_fini(_PyXIData_lookup_t *state)
|
||||||
_xidregistry_fini(&state->registry);
|
_xidregistry_fini(&state->registry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_lookup_context(PyThreadState *tstate, dlcontext_t *res)
|
||||||
|
{
|
||||||
|
_PyXI_global_state_t *global = _PyXI_GET_GLOBAL_STATE(tstate->interp);
|
||||||
|
if (global == NULL) {
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
_PyXI_state_t *local = _PyXI_GET_STATE(tstate->interp);
|
||||||
|
if (local == NULL) {
|
||||||
|
assert(PyErr_Occurred());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*res = (dlcontext_t){
|
||||||
|
.global = &global->data_lookup,
|
||||||
|
.local = &local->data_lookup,
|
||||||
|
};
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static xidatafunc
|
static xidatafunc
|
||||||
lookup_getdata(dlcontext_t *ctx, PyObject *obj)
|
lookup_getdata(dlcontext_t *ctx, PyObject *obj)
|
||||||
{
|
{
|
||||||
|
@ -38,32 +61,41 @@ lookup_getdata(dlcontext_t *ctx, PyObject *obj)
|
||||||
|
|
||||||
/* exported API */
|
/* exported API */
|
||||||
|
|
||||||
int
|
PyObject *
|
||||||
_PyXIData_GetLookupContext(PyInterpreterState *interp,
|
_PyXIData_GetNotShareableErrorType(PyThreadState *tstate)
|
||||||
_PyXIData_lookup_context_t *res)
|
|
||||||
{
|
{
|
||||||
_PyXI_global_state_t *global = _PyXI_GET_GLOBAL_STATE(interp);
|
PyObject *exctype = get_notshareableerror_type(tstate);
|
||||||
if (global == NULL) {
|
assert(exctype != NULL);
|
||||||
assert(PyErr_Occurred());
|
return exctype;
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
_PyXI_state_t *local = _PyXI_GET_STATE(interp);
|
|
||||||
if (local == NULL) {
|
|
||||||
assert(PyErr_Occurred());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
*res = (dlcontext_t){
|
|
||||||
.global = &global->data_lookup,
|
|
||||||
.local = &local->data_lookup,
|
|
||||||
.PyExc_NotShareableError = local->exceptions.PyExc_NotShareableError,
|
|
||||||
};
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
xidatafunc
|
void
|
||||||
_PyXIData_Lookup(_PyXIData_lookup_context_t *ctx, PyObject *obj)
|
_PyXIData_SetNotShareableError(PyThreadState *tstate, const char *msg)
|
||||||
{
|
{
|
||||||
return lookup_getdata(ctx, obj);
|
PyObject *cause = NULL;
|
||||||
|
set_notshareableerror(tstate, cause, 1, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyXIData_FormatNotShareableError(PyThreadState *tstate,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
PyObject *cause = NULL;
|
||||||
|
va_list vargs;
|
||||||
|
va_start(vargs, format);
|
||||||
|
format_notshareableerror_v(tstate, cause, 1, format, vargs);
|
||||||
|
va_end(vargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
xidatafunc
|
||||||
|
_PyXIData_Lookup(PyThreadState *tstate, PyObject *obj)
|
||||||
|
{
|
||||||
|
dlcontext_t ctx;
|
||||||
|
if (get_lookup_context(tstate, &ctx) < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return lookup_getdata(&ctx, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -250,7 +282,7 @@ _xidregistry_clear(dlregistry_t *xidregistry)
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyXIData_RegisterClass(_PyXIData_lookup_context_t *ctx,
|
_PyXIData_RegisterClass(PyThreadState *tstate,
|
||||||
PyTypeObject *cls, xidatafunc getdata)
|
PyTypeObject *cls, xidatafunc getdata)
|
||||||
{
|
{
|
||||||
if (!PyType_Check(cls)) {
|
if (!PyType_Check(cls)) {
|
||||||
|
@ -263,7 +295,11 @@ _PyXIData_RegisterClass(_PyXIData_lookup_context_t *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
int res = 0;
|
int res = 0;
|
||||||
dlregistry_t *xidregistry = _get_xidregistry_for_type(ctx, cls);
|
dlcontext_t ctx;
|
||||||
|
if (get_lookup_context(tstate, &ctx) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dlregistry_t *xidregistry = _get_xidregistry_for_type(&ctx, cls);
|
||||||
_xidregistry_lock(xidregistry);
|
_xidregistry_lock(xidregistry);
|
||||||
|
|
||||||
dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
|
dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
|
||||||
|
@ -281,10 +317,14 @@ _PyXIData_RegisterClass(_PyXIData_lookup_context_t *ctx,
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
_PyXIData_UnregisterClass(_PyXIData_lookup_context_t *ctx, PyTypeObject *cls)
|
_PyXIData_UnregisterClass(PyThreadState *tstate, PyTypeObject *cls)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
dlregistry_t *xidregistry = _get_xidregistry_for_type(ctx, cls);
|
dlcontext_t ctx;
|
||||||
|
if (get_lookup_context(tstate, &ctx) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
dlregistry_t *xidregistry = _get_xidregistry_for_type(&ctx, cls);
|
||||||
_xidregistry_lock(xidregistry);
|
_xidregistry_lock(xidregistry);
|
||||||
|
|
||||||
dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
|
dlregitem_t *matched = _xidregistry_find_type(xidregistry, cls);
|
||||||
|
@ -508,11 +548,6 @@ _tuple_shared_free(void* data)
|
||||||
static int
|
static int
|
||||||
_tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
|
_tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
|
||||||
{
|
{
|
||||||
dlcontext_t ctx;
|
|
||||||
if (_PyXIData_GetLookupContext(tstate->interp, &ctx) < 0) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_ssize_t len = PyTuple_GET_SIZE(obj);
|
Py_ssize_t len = PyTuple_GET_SIZE(obj);
|
||||||
if (len < 0) {
|
if (len < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -539,7 +574,7 @@ _tuple_shared(PyThreadState *tstate, PyObject *obj, _PyXIData_t *data)
|
||||||
|
|
||||||
int res = -1;
|
int res = -1;
|
||||||
if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) {
|
if (!_Py_EnterRecursiveCallTstate(tstate, " while sharing a tuple")) {
|
||||||
res = _PyObject_GetXIData(&ctx, item, data);
|
res = _PyObject_GetXIData(tstate, item, data);
|
||||||
_Py_LeaveRecursiveCallTstate(tstate);
|
_Py_LeaveRecursiveCallTstate(tstate);
|
||||||
}
|
}
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
|
|
|
@ -1,4 +1,25 @@
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ensure_current_cause(PyThreadState *tstate, PyObject *cause)
|
||||||
|
{
|
||||||
|
if (cause == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
PyObject *exc = _PyErr_GetRaisedException(tstate);
|
||||||
|
assert(exc != NULL);
|
||||||
|
PyObject *ctx = PyException_GetContext(exc);
|
||||||
|
if (ctx == NULL) {
|
||||||
|
PyException_SetContext(exc, Py_NewRef(cause));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Py_DECREF(ctx);
|
||||||
|
}
|
||||||
|
assert(PyException_GetCause(exc) == NULL);
|
||||||
|
PyException_SetCause(exc, Py_NewRef(cause));
|
||||||
|
_PyErr_SetRaisedException(tstate, exc);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* InterpreterError extends Exception */
|
/* InterpreterError extends Exception */
|
||||||
|
|
||||||
static PyTypeObject _PyExc_InterpreterError = {
|
static PyTypeObject _PyExc_InterpreterError = {
|
||||||
|
@ -25,6 +46,97 @@ static PyTypeObject _PyExc_InterpreterNotFoundError = {
|
||||||
};
|
};
|
||||||
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;
|
PyObject *PyExc_InterpreterNotFoundError = (PyObject *)&_PyExc_InterpreterNotFoundError;
|
||||||
|
|
||||||
|
/* NotShareableError extends ValueError */
|
||||||
|
|
||||||
|
static int
|
||||||
|
_init_notshareableerror(exceptions_t *state)
|
||||||
|
{
|
||||||
|
const char *name = "interpreters.NotShareableError";
|
||||||
|
// XXX Inherit from TypeError.
|
||||||
|
PyObject *base = PyExc_ValueError;
|
||||||
|
PyObject *ns = NULL;
|
||||||
|
PyObject *exctype = PyErr_NewException(name, base, ns);
|
||||||
|
if (exctype == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
state->PyExc_NotShareableError = exctype;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_fini_notshareableerror(exceptions_t *state)
|
||||||
|
{
|
||||||
|
Py_CLEAR(state->PyExc_NotShareableError);
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
get_notshareableerror_type(PyThreadState *tstate)
|
||||||
|
{
|
||||||
|
_PyXI_state_t *local = _PyXI_GET_STATE(tstate->interp);
|
||||||
|
if (local == NULL) {
|
||||||
|
PyErr_Clear();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return local->exceptions.PyExc_NotShareableError;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_ensure_notshareableerror(PyThreadState *tstate,
|
||||||
|
PyObject *cause, int force, PyObject *msgobj)
|
||||||
|
{
|
||||||
|
PyObject *ctx = _PyErr_GetRaisedException(tstate);
|
||||||
|
PyObject *exctype = get_notshareableerror_type(tstate);
|
||||||
|
if (exctype != NULL) {
|
||||||
|
if (!force && ctx != NULL && Py_TYPE(ctx) == (PyTypeObject *)exctype) {
|
||||||
|
// A NotShareableError instance is already set.
|
||||||
|
assert(cause == NULL);
|
||||||
|
_PyErr_SetRaisedException(tstate, ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
exctype = PyExc_ValueError;
|
||||||
|
}
|
||||||
|
_PyErr_SetObject(tstate, exctype, msgobj);
|
||||||
|
// We have to set the context manually since _PyErr_SetObject() doesn't.
|
||||||
|
_PyErr_ChainExceptions1Tstate(tstate, ctx);
|
||||||
|
_ensure_current_cause(tstate, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_notshareableerror(PyThreadState *tstate, PyObject *cause, int force, const char *msg)
|
||||||
|
{
|
||||||
|
PyObject *msgobj = PyUnicode_FromString(msg);
|
||||||
|
if (msgobj == NULL) {
|
||||||
|
assert(_PyErr_Occurred(tstate));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_ensure_notshareableerror(tstate, cause, force, msgobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
format_notshareableerror_v(PyThreadState *tstate, PyObject *cause, int force,
|
||||||
|
const char *format, va_list vargs)
|
||||||
|
{
|
||||||
|
PyObject *msgobj = PyUnicode_FromFormatV(format, vargs);
|
||||||
|
if (msgobj == NULL) {
|
||||||
|
assert(_PyErr_Occurred(tstate));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_ensure_notshareableerror(tstate, cause, force, msgobj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
format_notshareableerror(PyThreadState *tstate, PyObject *cause, int force,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
va_list vargs;
|
||||||
|
va_start(vargs, format);
|
||||||
|
format_notshareableerror_v(tstate, cause, force, format, vargs);
|
||||||
|
va_end(vargs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* lifecycle */
|
/* lifecycle */
|
||||||
|
|
||||||
|
@ -76,18 +188,9 @@ fini_static_exctypes(exceptions_t *state, PyInterpreterState *interp)
|
||||||
static int
|
static int
|
||||||
init_heap_exctypes(exceptions_t *state)
|
init_heap_exctypes(exceptions_t *state)
|
||||||
{
|
{
|
||||||
PyObject *exctype;
|
if (_init_notshareableerror(state) < 0) {
|
||||||
|
|
||||||
/* NotShareableError extends ValueError */
|
|
||||||
const char *name = "interpreters.NotShareableError";
|
|
||||||
PyObject *base = PyExc_ValueError;
|
|
||||||
PyObject *ns = NULL;
|
|
||||||
exctype = PyErr_NewException(name, base, ns);
|
|
||||||
if (exctype == NULL) {
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
state->PyExc_NotShareableError = exctype;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -98,5 +201,5 @@ init_heap_exctypes(exceptions_t *state)
|
||||||
static void
|
static void
|
||||||
fini_heap_exctypes(exceptions_t *state)
|
fini_heap_exctypes(exceptions_t *state)
|
||||||
{
|
{
|
||||||
Py_CLEAR(state->PyExc_NotShareableError);
|
_fini_notshareableerror(state);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Forward declarations */
|
|
||||||
static PyObject *
|
|
||||||
_PyErr_FormatV(PyThreadState *tstate, PyObject *exception,
|
|
||||||
const char *format, va_list vargs);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyErr_SetRaisedException(PyThreadState *tstate, PyObject *exc)
|
_PyErr_SetRaisedException(PyThreadState *tstate, PyObject *exc)
|
||||||
{
|
{
|
||||||
|
@ -699,12 +694,11 @@ _PyErr_ChainExceptions(PyObject *typ, PyObject *val, PyObject *tb)
|
||||||
The caller is responsible for ensuring that this call won't create
|
The caller is responsible for ensuring that this call won't create
|
||||||
any cycles in the exception context chain. */
|
any cycles in the exception context chain. */
|
||||||
void
|
void
|
||||||
_PyErr_ChainExceptions1(PyObject *exc)
|
_PyErr_ChainExceptions1Tstate(PyThreadState *tstate, PyObject *exc)
|
||||||
{
|
{
|
||||||
if (exc == NULL) {
|
if (exc == NULL) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
|
||||||
if (_PyErr_Occurred(tstate)) {
|
if (_PyErr_Occurred(tstate)) {
|
||||||
PyObject *exc2 = _PyErr_GetRaisedException(tstate);
|
PyObject *exc2 = _PyErr_GetRaisedException(tstate);
|
||||||
PyException_SetContext(exc2, exc);
|
PyException_SetContext(exc2, exc);
|
||||||
|
@ -715,6 +709,13 @@ _PyErr_ChainExceptions1(PyObject *exc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
_PyErr_ChainExceptions1(PyObject *exc)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
_PyErr_ChainExceptions1Tstate(tstate, exc);
|
||||||
|
}
|
||||||
|
|
||||||
/* If the current thread is handling an exception (exc_info is ), set this
|
/* If the current thread is handling an exception (exc_info is ), set this
|
||||||
exception as the context of the current raised exception.
|
exception as the context of the current raised exception.
|
||||||
|
|
||||||
|
@ -1061,15 +1062,14 @@ PyObject *PyErr_SetFromWindowsErrWithFilename(
|
||||||
#endif /* MS_WINDOWS */
|
#endif /* MS_WINDOWS */
|
||||||
|
|
||||||
static PyObject *
|
static PyObject *
|
||||||
_PyErr_SetImportErrorSubclassWithNameFrom(
|
new_importerror(
|
||||||
PyObject *exception, PyObject *msg,
|
PyThreadState *tstate, PyObject *exctype, PyObject *msg,
|
||||||
PyObject *name, PyObject *path, PyObject* from_name)
|
PyObject *name, PyObject *path, PyObject* from_name)
|
||||||
{
|
{
|
||||||
PyThreadState *tstate = _PyThreadState_GET();
|
PyObject *exc = NULL;
|
||||||
int issubclass;
|
PyObject *kwargs = NULL;
|
||||||
PyObject *kwargs, *error;
|
|
||||||
|
|
||||||
issubclass = PyObject_IsSubclass(exception, PyExc_ImportError);
|
int issubclass = PyObject_IsSubclass(exctype, PyExc_ImportError);
|
||||||
if (issubclass < 0) {
|
if (issubclass < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -1095,29 +1095,38 @@ _PyErr_SetImportErrorSubclassWithNameFrom(
|
||||||
from_name = Py_None;
|
from_name = Py_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
kwargs = PyDict_New();
|
kwargs = PyDict_New();
|
||||||
if (kwargs == NULL) {
|
if (kwargs == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (PyDict_SetItemString(kwargs, "name", name) < 0) {
|
if (PyDict_SetItemString(kwargs, "name", name) < 0) {
|
||||||
goto done;
|
goto finally;
|
||||||
}
|
}
|
||||||
if (PyDict_SetItemString(kwargs, "path", path) < 0) {
|
if (PyDict_SetItemString(kwargs, "path", path) < 0) {
|
||||||
goto done;
|
goto finally;
|
||||||
}
|
}
|
||||||
if (PyDict_SetItemString(kwargs, "name_from", from_name) < 0) {
|
if (PyDict_SetItemString(kwargs, "name_from", from_name) < 0) {
|
||||||
goto done;
|
goto finally;
|
||||||
}
|
}
|
||||||
|
exc = PyObject_VectorcallDict(exctype, &msg, 1, kwargs);
|
||||||
|
|
||||||
error = PyObject_VectorcallDict(exception, &msg, 1, kwargs);
|
finally:
|
||||||
|
Py_DECREF(kwargs);
|
||||||
|
return exc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
_PyErr_SetImportErrorSubclassWithNameFrom(
|
||||||
|
PyObject *exception, PyObject *msg,
|
||||||
|
PyObject *name, PyObject *path, PyObject* from_name)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
PyObject *error = new_importerror(
|
||||||
|
tstate, exception, msg, name, path, from_name);
|
||||||
if (error != NULL) {
|
if (error != NULL) {
|
||||||
_PyErr_SetObject(tstate, (PyObject *)Py_TYPE(error), error);
|
_PyErr_SetObject(tstate, (PyObject *)Py_TYPE(error), error);
|
||||||
Py_DECREF(error);
|
Py_DECREF(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
|
||||||
Py_DECREF(kwargs);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1141,6 +1150,29 @@ PyErr_SetImportError(PyObject *msg, PyObject *name, PyObject *path)
|
||||||
return PyErr_SetImportErrorSubclass(PyExc_ImportError, msg, name, path);
|
return PyErr_SetImportErrorSubclass(PyExc_ImportError, msg, name, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
_PyErr_SetModuleNotFoundError(PyObject *name)
|
||||||
|
{
|
||||||
|
PyThreadState *tstate = _PyThreadState_GET();
|
||||||
|
if (name == NULL) {
|
||||||
|
_PyErr_SetString(tstate, PyExc_TypeError, "expected a name argument");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PyObject *msg = PyUnicode_FromFormat("%S module not found", name);
|
||||||
|
if (msg == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
PyObject *exctype = PyExc_ModuleNotFoundError;
|
||||||
|
PyObject *exc = new_importerror(tstate, exctype, msg, name, NULL, NULL);
|
||||||
|
Py_DECREF(msg);
|
||||||
|
if (exc == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
_PyErr_SetObject(tstate, exctype, exc);
|
||||||
|
Py_DECREF(exc);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_PyErr_BadInternalCall(const char *filename, int lineno)
|
_PyErr_BadInternalCall(const char *filename, int lineno)
|
||||||
{
|
{
|
||||||
|
@ -1164,7 +1196,7 @@ PyErr_BadInternalCall(void)
|
||||||
#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
|
#define PyErr_BadInternalCall() _PyErr_BadInternalCall(__FILE__, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
static PyObject *
|
PyObject *
|
||||||
_PyErr_FormatV(PyThreadState *tstate, PyObject *exception,
|
_PyErr_FormatV(PyThreadState *tstate, PyObject *exception,
|
||||||
const char *format, va_list vargs)
|
const char *format, va_list vargs)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue