[pypy-commit] cffi default: Another attempt at improving the shutdown issues w.r.t. @def_extern
arigo
pypy.commits at gmail.com
Tue Mar 15 13:07:31 EDT 2016
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r2647:ab9941c073b3
Date: 2016-03-15 18:07 +0100
http://bitbucket.org/cffi/cffi/changeset/ab9941c073b3/
Log: Another attempt at improving the shutdown issues w.r.t. @def_extern
diff --git a/c/call_python.c b/c/call_python.c
--- a/c/call_python.c
+++ b/c/call_python.c
@@ -1,25 +1,52 @@
static PyObject *_get_interpstate_dict(void)
{
- /* hack around to return a dict that is subinterpreter-local */
+ /* Hack around to return a dict that is subinterpreter-local.
+ Does not return a new reference. Returns NULL in case of
+ error, but without setting any exception. (If called late
+ during shutdown, we *can't* set an exception!)
+ */
+ static PyObject *attr_name = NULL;
+ PyThreadState *tstate;
+ PyObject *d, *builtins;
int err;
- PyObject *m, *modules = PyThreadState_GET()->interp->modules;
- if (modules == NULL) {
- PyErr_SetString(FFIError, "subinterpreter already gone?");
+ tstate = PyThreadState_GET();
+ if (tstate == NULL) {
+ /* no thread state! */
return NULL;
}
- m = PyDict_GetItemString(modules, "_cffi_backend._extern_py");
- if (m == NULL) {
- m = PyModule_New("_cffi_backend._extern_py");
- if (m == NULL)
- return NULL;
- err = PyDict_SetItemString(modules, "_cffi_backend._extern_py", m);
- Py_DECREF(m); /* sys.modules keeps one reference to m */
+
+ builtins = tstate->interp->builtins;
+ if (builtins == NULL) {
+ /* subinterpreter was cleared already, or is being cleared right now,
+ to a point that is too much for us to continue */
+ return NULL;
+ }
+
+ /* from there on, we know the (sub-)interpreter is still valid */
+
+ if (attr_name == NULL) {
+ attr_name = PyString_InternFromString("__cffi_backend_extern_py");
+ if (attr_name == NULL)
+ goto error;
+ }
+
+ d = PyDict_GetItem(builtins, attr_name);
+ if (d == NULL) {
+ d = PyDict_New();
+ if (d == NULL)
+ goto error;
+ err = PyDict_SetItem(builtins, attr_name, d);
+ Py_DECREF(d); /* if successful, there is one ref left in builtins */
if (err < 0)
- return NULL;
+ goto error;
}
- return PyModule_GetDict(m);
+ return d;
+
+ error:
+ PyErr_Clear(); /* typically a MemoryError */
+ return NULL;
}
static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
@@ -77,7 +104,7 @@
interpstate_dict = _get_interpstate_dict();
if (interpstate_dict == NULL) {
Py_DECREF(infotuple);
- return NULL;
+ return PyErr_NoMemory();
}
externpy = (struct _cffi_externpy_s *)g->address;
@@ -119,7 +146,7 @@
interpstate_dict = _get_interpstate_dict();
if (interpstate_dict == NULL)
- goto error;
+ return 4; /* oops, shutdown issue? */
interpstate_key = PyLong_FromVoidPtr((void *)externpy);
if (interpstate_key == NULL)
@@ -219,8 +246,9 @@
if (err) {
static const char *msg[] = {
"no code was attached to it yet with @ffi.def_extern()",
- "got internal exception (out of memory / shutdown issue)",
+ "got internal exception (out of memory?)",
"@ffi.def_extern() was not called in the current subinterpreter",
+ "got internal exception (shutdown issue?)",
};
fprintf(stderr, "extern \"Python\": function %s() called, "
"but %s. Returning 0.\n", externpy->name, msg[err-1]);
More information about the pypy-commit
mailing list