aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/python/cffi/c/call_python.c
diff options
context:
space:
mode:
authorolegts <olegts@yandex-team.ru>2022-02-10 16:48:23 +0300
committerDaniil Cherednik <dcherednik@yandex-team.ru>2022-02-10 16:48:23 +0300
commit5eefa17021221fd267f1dd5f9d63d2493d131a8a (patch)
tree5d5cb817648f650d76cf1076100726fd9b8448e8 /contrib/python/cffi/c/call_python.c
parent30983fb2586f6904aaf6a5d6ef2b445cbaec1f44 (diff)
downloadydb-5eefa17021221fd267f1dd5f9d63d2493d131a8a.tar.gz
Restoring authorship annotation for <olegts@yandex-team.ru>. Commit 2 of 2.
Diffstat (limited to 'contrib/python/cffi/c/call_python.c')
-rw-r--r--contrib/python/cffi/c/call_python.c492
1 files changed, 246 insertions, 246 deletions
diff --git a/contrib/python/cffi/c/call_python.c b/contrib/python/cffi/c/call_python.c
index de2c5328df..d3d2e17810 100644
--- a/contrib/python/cffi/c/call_python.c
+++ b/contrib/python/cffi/c/call_python.c
@@ -1,7 +1,7 @@
#if PY_VERSION_HEX >= 0x03080000
# define HAVE_PYINTERPSTATE_GETDICT
#endif
-
+
static PyObject *_current_interp_key(void)
{
@@ -13,25 +13,25 @@ static PyObject *_current_interp_key(void)
#endif
}
-static PyObject *_get_interpstate_dict(void)
-{
- /* 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;
+static PyObject *_get_interpstate_dict(void)
+{
+ /* 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, *interpdict;
- int err;
+ int err;
PyInterpreterState *interp;
-
- tstate = PyThreadState_GET();
- if (tstate == NULL) {
- /* no thread state! */
- return NULL;
- }
-
+
+ tstate = PyThreadState_GET();
+ if (tstate == NULL) {
+ /* no thread state! */
+ return NULL;
+ }
+
interp = tstate->interp;
#ifdef HAVE_PYINTERPSTATE_GETDICT
interpdict = PyInterpreterState_GetDict(interp); /* shared reference */
@@ -39,164 +39,164 @@ static PyObject *_get_interpstate_dict(void)
interpdict = interp->builtins;
#endif
if (interpdict == 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 = PyText_InternFromString("__cffi_backend_extern_py");
- if (attr_name == NULL)
- goto error;
- }
-
+ /* 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 = PyText_InternFromString("__cffi_backend_extern_py");
+ if (attr_name == NULL)
+ goto error;
+ }
+
d = PyDict_GetItem(interpdict, attr_name);
- if (d == NULL) {
- d = PyDict_New();
- if (d == NULL)
- goto error;
+ if (d == NULL) {
+ d = PyDict_New();
+ if (d == NULL)
+ goto error;
err = PyDict_SetItem(interpdict, attr_name, d);
Py_DECREF(d); /* if successful, there is one ref left in interpdict */
- if (err < 0)
- goto error;
- }
- return d;
-
- error:
- PyErr_Clear(); /* typically a MemoryError */
- return NULL;
-}
-
-static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
-{
+ if (err < 0)
+ goto error;
+ }
+ return d;
+
+ error:
+ PyErr_Clear(); /* typically a MemoryError */
+ return NULL;
+}
+
+static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
+{
const char *s;
- PyObject *error, *onerror, *infotuple, *old1;
- int index, err;
- const struct _cffi_global_s *g;
- struct _cffi_externpy_s *externpy;
- CTypeDescrObject *ct;
- FFIObject *ffi;
- builder_c_t *types_builder;
- PyObject *name = NULL;
- PyObject *interpstate_dict;
- PyObject *interpstate_key;
-
- if (!PyArg_ParseTuple(outer_args, "OzOO", &ffi, &s, &error, &onerror))
- return NULL;
-
- if (s == NULL) {
- name = PyObject_GetAttrString(fn, "__name__");
- if (name == NULL)
- return NULL;
- s = PyText_AsUTF8(name);
- if (s == NULL) {
- Py_DECREF(name);
- return NULL;
- }
- }
-
- types_builder = &ffi->types_builder;
- index = search_in_globals(&types_builder->ctx, s, strlen(s));
- if (index < 0)
- goto not_found;
- g = &types_builder->ctx.globals[index];
- if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
- goto not_found;
- Py_XDECREF(name);
-
- ct = realize_c_type(types_builder, types_builder->ctx.types,
- _CFFI_GETARG(g->type_op));
- if (ct == NULL)
- return NULL;
-
- infotuple = prepare_callback_info_tuple(ct, fn, error, onerror, 0);
- Py_DECREF(ct);
- if (infotuple == NULL)
- return NULL;
-
- /* don't directly attach infotuple to externpy: in the presence of
- subinterpreters, each time we switch to a different
- subinterpreter and call the C function, it will notice the
- change and look up infotuple from the interpstate_dict.
- */
- interpstate_dict = _get_interpstate_dict();
- if (interpstate_dict == NULL) {
- Py_DECREF(infotuple);
- return PyErr_NoMemory();
- }
-
- externpy = (struct _cffi_externpy_s *)g->address;
- interpstate_key = PyLong_FromVoidPtr((void *)externpy);
- if (interpstate_key == NULL) {
- Py_DECREF(infotuple);
- return NULL;
- }
-
- err = PyDict_SetItem(interpstate_dict, interpstate_key, infotuple);
- Py_DECREF(interpstate_key);
- Py_DECREF(infotuple); /* interpstate_dict owns the last ref */
- if (err < 0)
- return NULL;
-
- /* force _update_cache_to_call_python() to be called the next time
- the C function invokes cffi_call_python, to update the cache */
- old1 = externpy->reserved1;
- externpy->reserved1 = Py_None; /* a non-NULL value */
- Py_INCREF(Py_None);
- Py_XDECREF(old1);
-
- /* return the function object unmodified */
- Py_INCREF(fn);
- return fn;
-
- not_found:
- PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
- "function with this name", s);
- Py_XDECREF(name);
- return NULL;
-}
-
-
-static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
-{
- PyObject *interpstate_dict, *interpstate_key, *infotuple, *old1, *new1;
- PyObject *old2;
-
- interpstate_dict = _get_interpstate_dict();
- if (interpstate_dict == NULL)
- return 4; /* oops, shutdown issue? */
-
- interpstate_key = PyLong_FromVoidPtr((void *)externpy);
- if (interpstate_key == NULL)
- goto error;
-
- infotuple = PyDict_GetItem(interpstate_dict, interpstate_key);
- Py_DECREF(interpstate_key);
- if (infotuple == NULL)
- return 3; /* no ffi.def_extern() from this subinterpreter */
-
+ PyObject *error, *onerror, *infotuple, *old1;
+ int index, err;
+ const struct _cffi_global_s *g;
+ struct _cffi_externpy_s *externpy;
+ CTypeDescrObject *ct;
+ FFIObject *ffi;
+ builder_c_t *types_builder;
+ PyObject *name = NULL;
+ PyObject *interpstate_dict;
+ PyObject *interpstate_key;
+
+ if (!PyArg_ParseTuple(outer_args, "OzOO", &ffi, &s, &error, &onerror))
+ return NULL;
+
+ if (s == NULL) {
+ name = PyObject_GetAttrString(fn, "__name__");
+ if (name == NULL)
+ return NULL;
+ s = PyText_AsUTF8(name);
+ if (s == NULL) {
+ Py_DECREF(name);
+ return NULL;
+ }
+ }
+
+ types_builder = &ffi->types_builder;
+ index = search_in_globals(&types_builder->ctx, s, strlen(s));
+ if (index < 0)
+ goto not_found;
+ g = &types_builder->ctx.globals[index];
+ if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
+ goto not_found;
+ Py_XDECREF(name);
+
+ ct = realize_c_type(types_builder, types_builder->ctx.types,
+ _CFFI_GETARG(g->type_op));
+ if (ct == NULL)
+ return NULL;
+
+ infotuple = prepare_callback_info_tuple(ct, fn, error, onerror, 0);
+ Py_DECREF(ct);
+ if (infotuple == NULL)
+ return NULL;
+
+ /* don't directly attach infotuple to externpy: in the presence of
+ subinterpreters, each time we switch to a different
+ subinterpreter and call the C function, it will notice the
+ change and look up infotuple from the interpstate_dict.
+ */
+ interpstate_dict = _get_interpstate_dict();
+ if (interpstate_dict == NULL) {
+ Py_DECREF(infotuple);
+ return PyErr_NoMemory();
+ }
+
+ externpy = (struct _cffi_externpy_s *)g->address;
+ interpstate_key = PyLong_FromVoidPtr((void *)externpy);
+ if (interpstate_key == NULL) {
+ Py_DECREF(infotuple);
+ return NULL;
+ }
+
+ err = PyDict_SetItem(interpstate_dict, interpstate_key, infotuple);
+ Py_DECREF(interpstate_key);
+ Py_DECREF(infotuple); /* interpstate_dict owns the last ref */
+ if (err < 0)
+ return NULL;
+
+ /* force _update_cache_to_call_python() to be called the next time
+ the C function invokes cffi_call_python, to update the cache */
+ old1 = externpy->reserved1;
+ externpy->reserved1 = Py_None; /* a non-NULL value */
+ Py_INCREF(Py_None);
+ Py_XDECREF(old1);
+
+ /* return the function object unmodified */
+ Py_INCREF(fn);
+ return fn;
+
+ not_found:
+ PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
+ "function with this name", s);
+ Py_XDECREF(name);
+ return NULL;
+}
+
+
+static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
+{
+ PyObject *interpstate_dict, *interpstate_key, *infotuple, *old1, *new1;
+ PyObject *old2;
+
+ interpstate_dict = _get_interpstate_dict();
+ if (interpstate_dict == NULL)
+ return 4; /* oops, shutdown issue? */
+
+ interpstate_key = PyLong_FromVoidPtr((void *)externpy);
+ if (interpstate_key == NULL)
+ goto error;
+
+ infotuple = PyDict_GetItem(interpstate_dict, interpstate_key);
+ Py_DECREF(interpstate_key);
+ if (infotuple == NULL)
+ return 3; /* no ffi.def_extern() from this subinterpreter */
+
new1 = _current_interp_key();
- Py_INCREF(new1);
- Py_INCREF(infotuple);
- old1 = (PyObject *)externpy->reserved1;
- old2 = (PyObject *)externpy->reserved2;
- externpy->reserved1 = new1; /* holds a reference */
- externpy->reserved2 = infotuple; /* holds a reference (issue #246) */
- Py_XDECREF(old1);
- Py_XDECREF(old2);
-
- return 0; /* no error */
-
- error:
- PyErr_Clear();
- return 2; /* out of memory? */
-}
-
-#if (defined(WITH_THREAD) && !defined(_MSC_VER) && \
- !defined(__amd64__) && !defined(__x86_64__) && \
- !defined(__i386__) && !defined(__i386))
+ Py_INCREF(new1);
+ Py_INCREF(infotuple);
+ old1 = (PyObject *)externpy->reserved1;
+ old2 = (PyObject *)externpy->reserved2;
+ externpy->reserved1 = new1; /* holds a reference */
+ externpy->reserved2 = infotuple; /* holds a reference (issue #246) */
+ Py_XDECREF(old1);
+ Py_XDECREF(old2);
+
+ return 0; /* no error */
+
+ error:
+ PyErr_Clear();
+ return 2; /* out of memory? */
+}
+
+#if (defined(WITH_THREAD) && !defined(_MSC_VER) && \
+ !defined(__amd64__) && !defined(__x86_64__) && \
+ !defined(__i386__) && !defined(__i386))
# if defined(HAVE_SYNC_SYNCHRONIZE)
# define read_barrier() __sync_synchronize()
# elif defined(_AIX)
@@ -211,82 +211,82 @@ static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
# warning "no definition for read_barrier(), missing synchronization for\
multi-thread initialization in embedded mode"
# endif
-#else
-# define read_barrier() (void)0
-#endif
-
-static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
-{
- /* Invoked by the helpers generated from extern "Python" in the cdef.
-
- 'externpy' is a static structure that describes which of the
- extern "Python" functions is called. It has got fields 'name' and
- 'type_index' describing the function, and more reserved fields
- that are initially zero. These reserved fields are set up by
- ffi.def_extern(), which invokes _ffi_def_extern_decorator() above.
-
- 'args' is a pointer to an array of 8-byte entries. Each entry
- contains an argument. If an argument is less than 8 bytes, only
- the part at the beginning of the entry is initialized. If an
- argument is 'long double' or a struct/union, then it is passed
- by reference.
-
- 'args' is also used as the place to write the result to
- (directly, even if more than 8 bytes). In all cases, 'args' is
- at least 8 bytes in size.
- */
- int err = 0;
-
- /* This read barrier is needed for _embedding.h. It is paired
- with the write_barrier() there. Without this barrier, we can
- in theory see the following situation: the Python
- initialization code already ran (in another thread), and the
- '_cffi_call_python' function pointer directed execution here;
- but any number of other data could still be seen as
- uninitialized below. For example, 'externpy' would still
- contain NULLs even though it was correctly set up, or
- 'interpreter_lock' (the GIL inside CPython) would still be seen
- as NULL, or 'autoInterpreterState' (used by
- PyGILState_Ensure()) would be NULL or contain bogus fields.
- */
- read_barrier();
-
- save_errno();
-
- /* We need the infotuple here. We could always go through
+#else
+# define read_barrier() (void)0
+#endif
+
+static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
+{
+ /* Invoked by the helpers generated from extern "Python" in the cdef.
+
+ 'externpy' is a static structure that describes which of the
+ extern "Python" functions is called. It has got fields 'name' and
+ 'type_index' describing the function, and more reserved fields
+ that are initially zero. These reserved fields are set up by
+ ffi.def_extern(), which invokes _ffi_def_extern_decorator() above.
+
+ 'args' is a pointer to an array of 8-byte entries. Each entry
+ contains an argument. If an argument is less than 8 bytes, only
+ the part at the beginning of the entry is initialized. If an
+ argument is 'long double' or a struct/union, then it is passed
+ by reference.
+
+ 'args' is also used as the place to write the result to
+ (directly, even if more than 8 bytes). In all cases, 'args' is
+ at least 8 bytes in size.
+ */
+ int err = 0;
+
+ /* This read barrier is needed for _embedding.h. It is paired
+ with the write_barrier() there. Without this barrier, we can
+ in theory see the following situation: the Python
+ initialization code already ran (in another thread), and the
+ '_cffi_call_python' function pointer directed execution here;
+ but any number of other data could still be seen as
+ uninitialized below. For example, 'externpy' would still
+ contain NULLs even though it was correctly set up, or
+ 'interpreter_lock' (the GIL inside CPython) would still be seen
+ as NULL, or 'autoInterpreterState' (used by
+ PyGILState_Ensure()) would be NULL or contain bogus fields.
+ */
+ read_barrier();
+
+ save_errno();
+
+ /* We need the infotuple here. We could always go through
_update_cache_to_call_python(), but to avoid the extra dict
- lookups, we cache in (reserved1, reserved2) the last seen pair
+ lookups, we cache in (reserved1, reserved2) the last seen pair
(interp->modules, infotuple). The first item in this tuple is
a random PyObject that identifies the subinterpreter.
- */
- if (externpy->reserved1 == NULL) {
- /* Not initialized! We didn't call @ffi.def_extern() on this
- externpy object from any subinterpreter at all. */
- err = 1;
- }
- else {
- PyGILState_STATE state = gil_ensure();
+ */
+ if (externpy->reserved1 == NULL) {
+ /* Not initialized! We didn't call @ffi.def_extern() on this
+ externpy object from any subinterpreter at all. */
+ err = 1;
+ }
+ else {
+ PyGILState_STATE state = gil_ensure();
if (externpy->reserved1 != _current_interp_key()) {
- /* Update the (reserved1, reserved2) cache. This will fail
- if we didn't call @ffi.def_extern() in this particular
- subinterpreter. */
- err = _update_cache_to_call_python(externpy);
- }
- if (!err) {
- general_invoke_callback(0, args, args, externpy->reserved2);
- }
- gil_release(state);
- }
- if (err) {
- static const char *msg[] = {
- "no code was attached to it yet with @ffi.def_extern()",
- "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]);
- memset(args, 0, externpy->size_of_result);
- }
- restore_errno();
-}
+ /* Update the (reserved1, reserved2) cache. This will fail
+ if we didn't call @ffi.def_extern() in this particular
+ subinterpreter. */
+ err = _update_cache_to_call_python(externpy);
+ }
+ if (!err) {
+ general_invoke_callback(0, args, args, externpy->reserved2);
+ }
+ gil_release(state);
+ }
+ if (err) {
+ static const char *msg[] = {
+ "no code was attached to it yet with @ffi.def_extern()",
+ "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]);
+ memset(args, 0, externpy->size_of_result);
+ }
+ restore_errno();
+}