1 #if PY_VERSION_HEX >= 0x03080000
2 # define HAVE_PYINTERPSTATE_GETDICT
3 #endif
4
5
_current_interp_key(void)6 static PyObject *_current_interp_key(void)
7 {
8 PyInterpreterState *interp = PyThreadState_GET()->interp;
9 #ifdef HAVE_PYINTERPSTATE_GETDICT
10 return PyInterpreterState_GetDict(interp); /* shared reference */
11 #else
12 return interp->modules;
13 #endif
14 }
15
_get_interpstate_dict(void)16 static PyObject *_get_interpstate_dict(void)
17 {
18 /* Hack around to return a dict that is subinterpreter-local.
19 Does not return a new reference. Returns NULL in case of
20 error, but without setting any exception. (If called late
21 during shutdown, we *can't* set an exception!)
22 */
23 static PyObject *attr_name = NULL;
24 PyThreadState *tstate;
25 PyObject *d, *interpdict;
26 int err;
27 PyInterpreterState *interp;
28
29 tstate = PyThreadState_GET();
30 if (tstate == NULL) {
31 /* no thread state! */
32 return NULL;
33 }
34
35 interp = tstate->interp;
36 #ifdef HAVE_PYINTERPSTATE_GETDICT
37 interpdict = PyInterpreterState_GetDict(interp); /* shared reference */
38 #else
39 interpdict = interp->builtins;
40 #endif
41 if (interpdict == NULL) {
42 /* subinterpreter was cleared already, or is being cleared right now,
43 to a point that is too much for us to continue */
44 return NULL;
45 }
46
47 /* from there on, we know the (sub-)interpreter is still valid */
48
49 if (attr_name == NULL) {
50 attr_name = PyText_InternFromString("__cffi_backend_extern_py");
51 if (attr_name == NULL)
52 goto error;
53 }
54
55 d = PyDict_GetItem(interpdict, attr_name);
56 if (d == NULL) {
57 d = PyDict_New();
58 if (d == NULL)
59 goto error;
60 err = PyDict_SetItem(interpdict, attr_name, d);
61 Py_DECREF(d); /* if successful, there is one ref left in interpdict */
62 if (err < 0)
63 goto error;
64 }
65 return d;
66
67 error:
68 PyErr_Clear(); /* typically a MemoryError */
69 return NULL;
70 }
71
_ffi_def_extern_decorator(PyObject * outer_args,PyObject * fn)72 static PyObject *_ffi_def_extern_decorator(PyObject *outer_args, PyObject *fn)
73 {
74 const char *s;
75 PyObject *error, *onerror, *infotuple, *old1;
76 int index, err;
77 const struct _cffi_global_s *g;
78 struct _cffi_externpy_s *externpy;
79 CTypeDescrObject *ct;
80 FFIObject *ffi;
81 builder_c_t *types_builder;
82 PyObject *name = NULL;
83 PyObject *interpstate_dict;
84 PyObject *interpstate_key;
85
86 if (!PyArg_ParseTuple(outer_args, "OzOO", &ffi, &s, &error, &onerror))
87 return NULL;
88
89 if (s == NULL) {
90 name = PyObject_GetAttrString(fn, "__name__");
91 if (name == NULL)
92 return NULL;
93 s = PyText_AsUTF8(name);
94 if (s == NULL) {
95 Py_DECREF(name);
96 return NULL;
97 }
98 }
99
100 types_builder = &ffi->types_builder;
101 index = search_in_globals(&types_builder->ctx, s, strlen(s));
102 if (index < 0)
103 goto not_found;
104 g = &types_builder->ctx.globals[index];
105 if (_CFFI_GETOP(g->type_op) != _CFFI_OP_EXTERN_PYTHON)
106 goto not_found;
107 Py_XDECREF(name);
108
109 ct = realize_c_type(types_builder, types_builder->ctx.types,
110 _CFFI_GETARG(g->type_op));
111 if (ct == NULL)
112 return NULL;
113
114 infotuple = prepare_callback_info_tuple(ct, fn, error, onerror, 0);
115 Py_DECREF(ct);
116 if (infotuple == NULL)
117 return NULL;
118
119 /* don't directly attach infotuple to externpy: in the presence of
120 subinterpreters, each time we switch to a different
121 subinterpreter and call the C function, it will notice the
122 change and look up infotuple from the interpstate_dict.
123 */
124 interpstate_dict = _get_interpstate_dict();
125 if (interpstate_dict == NULL) {
126 Py_DECREF(infotuple);
127 return PyErr_NoMemory();
128 }
129
130 externpy = (struct _cffi_externpy_s *)g->address;
131 interpstate_key = PyLong_FromVoidPtr((void *)externpy);
132 if (interpstate_key == NULL) {
133 Py_DECREF(infotuple);
134 return NULL;
135 }
136
137 err = PyDict_SetItem(interpstate_dict, interpstate_key, infotuple);
138 Py_DECREF(interpstate_key);
139 Py_DECREF(infotuple); /* interpstate_dict owns the last ref */
140 if (err < 0)
141 return NULL;
142
143 /* force _update_cache_to_call_python() to be called the next time
144 the C function invokes cffi_call_python, to update the cache */
145 old1 = externpy->reserved1;
146 externpy->reserved1 = Py_None; /* a non-NULL value */
147 Py_INCREF(Py_None);
148 Py_XDECREF(old1);
149
150 /* return the function object unmodified */
151 Py_INCREF(fn);
152 return fn;
153
154 not_found:
155 PyErr_Format(FFIError, "ffi.def_extern('%s'): no 'extern \"Python\"' "
156 "function with this name", s);
157 Py_XDECREF(name);
158 return NULL;
159 }
160
161
_update_cache_to_call_python(struct _cffi_externpy_s * externpy)162 static int _update_cache_to_call_python(struct _cffi_externpy_s *externpy)
163 {
164 PyObject *interpstate_dict, *interpstate_key, *infotuple, *old1, *new1;
165 PyObject *old2;
166
167 interpstate_dict = _get_interpstate_dict();
168 if (interpstate_dict == NULL)
169 return 4; /* oops, shutdown issue? */
170
171 interpstate_key = PyLong_FromVoidPtr((void *)externpy);
172 if (interpstate_key == NULL)
173 goto error;
174
175 infotuple = PyDict_GetItem(interpstate_dict, interpstate_key);
176 Py_DECREF(interpstate_key);
177 if (infotuple == NULL)
178 return 3; /* no ffi.def_extern() from this subinterpreter */
179
180 new1 = _current_interp_key();
181 Py_INCREF(new1);
182 Py_INCREF(infotuple);
183 old1 = (PyObject *)externpy->reserved1;
184 old2 = (PyObject *)externpy->reserved2;
185 externpy->reserved1 = new1; /* holds a reference */
186 externpy->reserved2 = infotuple; /* holds a reference (issue #246) */
187 Py_XDECREF(old1);
188 Py_XDECREF(old2);
189
190 return 0; /* no error */
191
192 error:
193 PyErr_Clear();
194 return 2; /* out of memory? */
195 }
196
197 #if (defined(WITH_THREAD) && !defined(_MSC_VER) && \
198 !defined(__amd64__) && !defined(__x86_64__) && \
199 !defined(__i386__) && !defined(__i386))
200 # if defined(HAVE_SYNC_SYNCHRONIZE)
201 # define read_barrier() __sync_synchronize()
202 # elif defined(_AIX)
203 # define read_barrier() __lwsync()
204 # elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
205 # include <mbarrier.h>
206 # define read_barrier() __compiler_barrier()
207 # elif defined(__hpux)
208 # define read_barrier() _Asm_mf()
209 # else
210 # define read_barrier() /* missing */
211 # warning "no definition for read_barrier(), missing synchronization for\
212 multi-thread initialization in embedded mode"
213 # endif
214 #else
215 # define read_barrier() (void)0
216 #endif
217
cffi_call_python(struct _cffi_externpy_s * externpy,char * args)218 static void cffi_call_python(struct _cffi_externpy_s *externpy, char *args)
219 {
220 /* Invoked by the helpers generated from extern "Python" in the cdef.
221
222 'externpy' is a static structure that describes which of the
223 extern "Python" functions is called. It has got fields 'name' and
224 'type_index' describing the function, and more reserved fields
225 that are initially zero. These reserved fields are set up by
226 ffi.def_extern(), which invokes _ffi_def_extern_decorator() above.
227
228 'args' is a pointer to an array of 8-byte entries. Each entry
229 contains an argument. If an argument is less than 8 bytes, only
230 the part at the beginning of the entry is initialized. If an
231 argument is 'long double' or a struct/union, then it is passed
232 by reference.
233
234 'args' is also used as the place to write the result to
235 (directly, even if more than 8 bytes). In all cases, 'args' is
236 at least 8 bytes in size.
237 */
238 int err = 0;
239
240 /* This read barrier is needed for _embedding.h. It is paired
241 with the write_barrier() there. Without this barrier, we can
242 in theory see the following situation: the Python
243 initialization code already ran (in another thread), and the
244 '_cffi_call_python' function pointer directed execution here;
245 but any number of other data could still be seen as
246 uninitialized below. For example, 'externpy' would still
247 contain NULLs even though it was correctly set up, or
248 'interpreter_lock' (the GIL inside CPython) would still be seen
249 as NULL, or 'autoInterpreterState' (used by
250 PyGILState_Ensure()) would be NULL or contain bogus fields.
251 */
252 read_barrier();
253
254 save_errno();
255
256 /* We need the infotuple here. We could always go through
257 _update_cache_to_call_python(), but to avoid the extra dict
258 lookups, we cache in (reserved1, reserved2) the last seen pair
259 (interp->modules, infotuple). The first item in this tuple is
260 a random PyObject that identifies the subinterpreter.
261 */
262 if (externpy->reserved1 == NULL) {
263 /* Not initialized! We didn't call @ffi.def_extern() on this
264 externpy object from any subinterpreter at all. */
265 err = 1;
266 }
267 else {
268 PyGILState_STATE state = gil_ensure();
269 if (externpy->reserved1 != _current_interp_key()) {
270 /* Update the (reserved1, reserved2) cache. This will fail
271 if we didn't call @ffi.def_extern() in this particular
272 subinterpreter. */
273 err = _update_cache_to_call_python(externpy);
274 }
275 if (!err) {
276 general_invoke_callback(0, args, args, externpy->reserved2);
277 }
278 gil_release(state);
279 }
280 if (err) {
281 static const char *msg[] = {
282 "no code was attached to it yet with @ffi.def_extern()",
283 "got internal exception (out of memory?)",
284 "@ffi.def_extern() was not called in the current subinterpreter",
285 "got internal exception (shutdown issue?)",
286 };
287 fprintf(stderr, "extern \"Python\": function %s() called, "
288 "but %s. Returning 0.\n", externpy->name, msg[err-1]);
289 memset(args, 0, externpy->size_of_result);
290 }
291 restore_errno();
292 }
293