1
2 /***** Support code for embedding *****/
3
4 #ifdef __cplusplus
5 extern "C" {
6 #endif
7
8
9 #if defined(_WIN32)
10 # define CFFI_DLLEXPORT __declspec(dllexport)
11 #elif defined(__GNUC__)
12 # define CFFI_DLLEXPORT __attribute__((visibility("default")))
13 #else
14 # define CFFI_DLLEXPORT /* nothing */
15 #endif
16
17
18 /* There are two global variables of type _cffi_call_python_fnptr:
19
20 * _cffi_call_python, which we declare just below, is the one called
21 by ``extern "Python"`` implementations.
22
23 * _cffi_call_python_org, which on CPython is actually part of the
24 _cffi_exports[] array, is the function pointer copied from
25 _cffi_backend.
26
27 After initialization is complete, both are equal. However, the
28 first one remains equal to &_cffi_start_and_call_python until the
29 very end of initialization, when we are (or should be) sure that
30 concurrent threads also see a completely initialized world, and
31 only then is it changed.
32 */
33 #undef _cffi_call_python
34 typedef void (*_cffi_call_python_fnptr)(struct _cffi_externpy_s *, char *);
35 static void _cffi_start_and_call_python(struct _cffi_externpy_s *, char *);
36 static _cffi_call_python_fnptr _cffi_call_python = &_cffi_start_and_call_python;
37
38
39 #ifndef _MSC_VER
40 /* --- Assuming a GCC not infinitely old --- */
41 # define cffi_compare_and_swap(l,o,n) __sync_bool_compare_and_swap(l,o,n)
42 # define cffi_write_barrier() __sync_synchronize()
43 # if !defined(__amd64__) && !defined(__x86_64__) && \
44 !defined(__i386__) && !defined(__i386)
45 # define cffi_read_barrier() __sync_synchronize()
46 # else
47 # define cffi_read_barrier() (void)0
48 # endif
49 #else
50 /* --- Windows threads version --- */
51 # include <Windows.h>
52 # define cffi_compare_and_swap(l,o,n) \
53 (InterlockedCompareExchangePointer(l,n,o) == (o))
54 # define cffi_write_barrier() InterlockedCompareExchange(&_cffi_dummy,0,0)
55 # define cffi_read_barrier() (void)0
56 static volatile LONG _cffi_dummy;
57 #endif
58
59 #ifdef WITH_THREAD
60 # ifndef _MSC_VER
61 # include <pthread.h>
62 static pthread_mutex_t _cffi_embed_startup_lock;
63 # else
64 static CRITICAL_SECTION _cffi_embed_startup_lock;
65 # endif
66 static char _cffi_embed_startup_lock_ready = 0;
67 #endif
68
_cffi_acquire_reentrant_mutex(void)69 static void _cffi_acquire_reentrant_mutex(void)
70 {
71 static void *volatile lock = NULL;
72
73 while (!cffi_compare_and_swap(&lock, NULL, (void *)1)) {
74 /* should ideally do a spin loop instruction here, but
75 hard to do it portably and doesn't really matter I
76 think: pthread_mutex_init() should be very fast, and
77 this is only run at start-up anyway. */
78 }
79
80 #ifdef WITH_THREAD
81 if (!_cffi_embed_startup_lock_ready) {
82 # ifndef _MSC_VER
83 pthread_mutexattr_t attr;
84 pthread_mutexattr_init(&attr);
85 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
86 pthread_mutex_init(&_cffi_embed_startup_lock, &attr);
87 # else
88 InitializeCriticalSection(&_cffi_embed_startup_lock);
89 # endif
90 _cffi_embed_startup_lock_ready = 1;
91 }
92 #endif
93
94 while (!cffi_compare_and_swap(&lock, (void *)1, NULL))
95 ;
96
97 #ifndef _MSC_VER
98 pthread_mutex_lock(&_cffi_embed_startup_lock);
99 #else
100 EnterCriticalSection(&_cffi_embed_startup_lock);
101 #endif
102 }
103
_cffi_release_reentrant_mutex(void)104 static void _cffi_release_reentrant_mutex(void)
105 {
106 #ifndef _MSC_VER
107 pthread_mutex_unlock(&_cffi_embed_startup_lock);
108 #else
109 LeaveCriticalSection(&_cffi_embed_startup_lock);
110 #endif
111 }
112
113
114 /********** CPython-specific section **********/
115 #ifndef PYPY_VERSION
116
117 #include "_cffi_errors.h"
118
119
120 #define _cffi_call_python_org _cffi_exports[_CFFI_CPIDX]
121
122 PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(void); /* forward */
123
_cffi_py_initialize(void)124 static void _cffi_py_initialize(void)
125 {
126 /* XXX use initsigs=0, which "skips initialization registration of
127 signal handlers, which might be useful when Python is
128 embedded" according to the Python docs. But review and think
129 if it should be a user-controllable setting.
130
131 XXX we should also give a way to write errors to a buffer
132 instead of to stderr.
133
134 XXX if importing 'site' fails, CPython (any version) calls
135 exit(). Should we try to work around this behavior here?
136 */
137 Py_InitializeEx(0);
138 }
139
_cffi_initialize_python(void)140 static int _cffi_initialize_python(void)
141 {
142 /* This initializes Python, imports _cffi_backend, and then the
143 present .dll/.so is set up as a CPython C extension module.
144 */
145 int result;
146 PyGILState_STATE state;
147 PyObject *pycode=NULL, *global_dict=NULL, *x;
148 PyObject *builtins;
149
150 state = PyGILState_Ensure();
151
152 /* Call the initxxx() function from the present module. It will
153 create and initialize us as a CPython extension module, instead
154 of letting the startup Python code do it---it might reimport
155 the same .dll/.so and get maybe confused on some platforms.
156 It might also have troubles locating the .dll/.so again for all
157 I know.
158 */
159 (void)_CFFI_PYTHON_STARTUP_FUNC();
160 if (PyErr_Occurred())
161 goto error;
162
163 /* Now run the Python code provided to ffi.embedding_init_code().
164 */
165 pycode = Py_CompileString(_CFFI_PYTHON_STARTUP_CODE,
166 "<init code for '" _CFFI_MODULE_NAME "'>",
167 Py_file_input);
168 if (pycode == NULL)
169 goto error;
170 global_dict = PyDict_New();
171 if (global_dict == NULL)
172 goto error;
173 builtins = PyEval_GetBuiltins();
174 if (builtins == NULL)
175 goto error;
176 if (PyDict_SetItemString(global_dict, "__builtins__", builtins) < 0)
177 goto error;
178 x = PyEval_EvalCode(
179 #if PY_MAJOR_VERSION < 3
180 (PyCodeObject *)
181 #endif
182 pycode, global_dict, global_dict);
183 if (x == NULL)
184 goto error;
185 Py_DECREF(x);
186
187 /* Done! Now if we've been called from
188 _cffi_start_and_call_python() in an ``extern "Python"``, we can
189 only hope that the Python code did correctly set up the
190 corresponding @ffi.def_extern() function. Otherwise, the
191 general logic of ``extern "Python"`` functions (inside the
192 _cffi_backend module) will find that the reference is still
193 missing and print an error.
194 */
195 result = 0;
196 done:
197 Py_XDECREF(pycode);
198 Py_XDECREF(global_dict);
199 PyGILState_Release(state);
200 return result;
201
202 error:;
203 {
204 /* Print as much information as potentially useful.
205 Debugging load-time failures with embedding is not fun
206 */
207 PyObject *ecap;
208 PyObject *exception, *v, *tb, *f, *modules, *mod;
209 PyErr_Fetch(&exception, &v, &tb);
210 ecap = _cffi_start_error_capture();
211 f = PySys_GetObject((char *)"stderr");
212 if (f != NULL && f != Py_None) {
213 PyFile_WriteString(
214 "Failed to initialize the Python-CFFI embedding logic:\n\n", f);
215 }
216
217 if (exception != NULL) {
218 PyErr_NormalizeException(&exception, &v, &tb);
219 PyErr_Display(exception, v, tb);
220 }
221 Py_XDECREF(exception);
222 Py_XDECREF(v);
223 Py_XDECREF(tb);
224
225 if (f != NULL && f != Py_None) {
226 PyFile_WriteString("\nFrom: " _CFFI_MODULE_NAME
227 "\ncompiled with cffi version: 1.15.0"
228 "\n_cffi_backend module: ", f);
229 modules = PyImport_GetModuleDict();
230 mod = PyDict_GetItemString(modules, "_cffi_backend");
231 if (mod == NULL) {
232 PyFile_WriteString("not loaded", f);
233 }
234 else {
235 v = PyObject_GetAttrString(mod, "__file__");
236 PyFile_WriteObject(v, f, 0);
237 Py_XDECREF(v);
238 }
239 PyFile_WriteString("\nsys.path: ", f);
240 PyFile_WriteObject(PySys_GetObject((char *)"path"), f, 0);
241 PyFile_WriteString("\n\n", f);
242 }
243 _cffi_stop_error_capture(ecap);
244 }
245 result = -1;
246 goto done;
247 }
248
249 #if PY_VERSION_HEX < 0x03080000
250 PyAPI_DATA(char *) _PyParser_TokenNames[]; /* from CPython */
251 #endif
252
_cffi_carefully_make_gil(void)253 static int _cffi_carefully_make_gil(void)
254 {
255 /* This does the basic initialization of Python. It can be called
256 completely concurrently from unrelated threads. It assumes
257 that we don't hold the GIL before (if it exists), and we don't
258 hold it afterwards.
259
260 (What it really does used to be completely different in Python 2
261 and Python 3, with the Python 2 solution avoiding the spin-lock
262 around the Py_InitializeEx() call. However, after recent changes
263 to CPython 2.7 (issue #358) it no longer works. So we use the
264 Python 3 solution everywhere.)
265
266 This initializes Python by calling Py_InitializeEx().
267 Important: this must not be called concurrently at all.
268 So we use a global variable as a simple spin lock. This global
269 variable must be from 'libpythonX.Y.so', not from this
270 cffi-based extension module, because it must be shared from
271 different cffi-based extension modules.
272
273 In Python < 3.8, we choose
274 _PyParser_TokenNames[0] as a completely arbitrary pointer value
275 that is never written to. The default is to point to the
276 string "ENDMARKER". We change it temporarily to point to the
277 next character in that string. (Yes, I know it's REALLY
278 obscure.)
279
280 In Python >= 3.8, this string array is no longer writable, so
281 instead we pick PyCapsuleType.tp_version_tag. We can't change
282 Python < 3.8 because someone might use a mixture of cffi
283 embedded modules, some of which were compiled before this file
284 changed.
285 */
286
287 #ifdef WITH_THREAD
288 # if PY_VERSION_HEX < 0x03080000
289 char *volatile *lock = (char *volatile *)_PyParser_TokenNames;
290 char *old_value, *locked_value;
291
292 while (1) { /* spin loop */
293 old_value = *lock;
294 locked_value = old_value + 1;
295 if (old_value[0] == 'E') {
296 assert(old_value[1] == 'N');
297 if (cffi_compare_and_swap(lock, old_value, locked_value))
298 break;
299 }
300 else {
301 assert(old_value[0] == 'N');
302 /* should ideally do a spin loop instruction here, but
303 hard to do it portably and doesn't really matter I
304 think: PyEval_InitThreads() should be very fast, and
305 this is only run at start-up anyway. */
306 }
307 }
308 # else
309 int volatile *lock = (int volatile *)&PyCapsule_Type.tp_version_tag;
310 int old_value, locked_value;
311 assert(!(PyCapsule_Type.tp_flags & Py_TPFLAGS_HAVE_VERSION_TAG));
312
313 while (1) { /* spin loop */
314 old_value = *lock;
315 locked_value = -42;
316 if (old_value == 0) {
317 if (cffi_compare_and_swap(lock, old_value, locked_value))
318 break;
319 }
320 else {
321 assert(old_value == locked_value);
322 /* should ideally do a spin loop instruction here, but
323 hard to do it portably and doesn't really matter I
324 think: PyEval_InitThreads() should be very fast, and
325 this is only run at start-up anyway. */
326 }
327 }
328 # endif
329 #endif
330
331 /* call Py_InitializeEx() */
332 if (!Py_IsInitialized()) {
333 _cffi_py_initialize();
334 #if PY_VERSION_HEX < 0x03070000
335 PyEval_InitThreads();
336 #endif
337 PyEval_SaveThread(); /* release the GIL */
338 /* the returned tstate must be the one that has been stored into the
339 autoTLSkey by _PyGILState_Init() called from Py_Initialize(). */
340 }
341 else {
342 #if PY_VERSION_HEX < 0x03070000
343 /* PyEval_InitThreads() is always a no-op from CPython 3.7 */
344 PyGILState_STATE state = PyGILState_Ensure();
345 PyEval_InitThreads();
346 PyGILState_Release(state);
347 #endif
348 }
349
350 #ifdef WITH_THREAD
351 /* release the lock */
352 while (!cffi_compare_and_swap(lock, locked_value, old_value))
353 ;
354 #endif
355
356 return 0;
357 }
358
359 /********** end CPython-specific section **********/
360
361
362 #else
363
364
365 /********** PyPy-specific section **********/
366
367 PyMODINIT_FUNC _CFFI_PYTHON_STARTUP_FUNC(const void *[]); /* forward */
368
369 static struct _cffi_pypy_init_s {
370 const char *name;
371 void *func; /* function pointer */
372 const char *code;
373 } _cffi_pypy_init = {
374 _CFFI_MODULE_NAME,
375 _CFFI_PYTHON_STARTUP_FUNC,
376 _CFFI_PYTHON_STARTUP_CODE,
377 };
378
379 extern int pypy_carefully_make_gil(const char *);
380 extern int pypy_init_embedded_cffi_module(int, struct _cffi_pypy_init_s *);
381
_cffi_carefully_make_gil(void)382 static int _cffi_carefully_make_gil(void)
383 {
384 return pypy_carefully_make_gil(_CFFI_MODULE_NAME);
385 }
386
_cffi_initialize_python(void)387 static int _cffi_initialize_python(void)
388 {
389 return pypy_init_embedded_cffi_module(0xB011, &_cffi_pypy_init);
390 }
391
392 /********** end PyPy-specific section **********/
393
394
395 #endif
396
397
398 #ifdef __GNUC__
399 __attribute__((noinline))
400 #endif
_cffi_start_python(void)401 static _cffi_call_python_fnptr _cffi_start_python(void)
402 {
403 /* Delicate logic to initialize Python. This function can be
404 called multiple times concurrently, e.g. when the process calls
405 its first ``extern "Python"`` functions in multiple threads at
406 once. It can also be called recursively, in which case we must
407 ignore it. We also have to consider what occurs if several
408 different cffi-based extensions reach this code in parallel
409 threads---it is a different copy of the code, then, and we
410 can't have any shared global variable unless it comes from
411 'libpythonX.Y.so'.
412
413 Idea:
414
415 * _cffi_carefully_make_gil(): "carefully" call
416 PyEval_InitThreads() (possibly with Py_InitializeEx() first).
417
418 * then we use a (local) custom lock to make sure that a call to this
419 cffi-based extension will wait if another call to the *same*
420 extension is running the initialization in another thread.
421 It is reentrant, so that a recursive call will not block, but
422 only one from a different thread.
423
424 * then we grab the GIL and (Python 2) we call Py_InitializeEx().
425 At this point, concurrent calls to Py_InitializeEx() are not
426 possible: we have the GIL.
427
428 * do the rest of the specific initialization, which may
429 temporarily release the GIL but not the custom lock.
430 Only release the custom lock when we are done.
431 */
432 static char called = 0;
433
434 if (_cffi_carefully_make_gil() != 0)
435 return NULL;
436
437 _cffi_acquire_reentrant_mutex();
438
439 /* Here the GIL exists, but we don't have it. We're only protected
440 from concurrency by the reentrant mutex. */
441
442 /* This file only initializes the embedded module once, the first
443 time this is called, even if there are subinterpreters. */
444 if (!called) {
445 called = 1; /* invoke _cffi_initialize_python() only once,
446 but don't set '_cffi_call_python' right now,
447 otherwise concurrent threads won't call
448 this function at all (we need them to wait) */
449 if (_cffi_initialize_python() == 0) {
450 /* now initialization is finished. Switch to the fast-path. */
451
452 /* We would like nobody to see the new value of
453 '_cffi_call_python' without also seeing the rest of the
454 data initialized. However, this is not possible. But
455 the new value of '_cffi_call_python' is the function
456 'cffi_call_python()' from _cffi_backend. So: */
457 cffi_write_barrier();
458 /* ^^^ we put a write barrier here, and a corresponding
459 read barrier at the start of cffi_call_python(). This
460 ensures that after that read barrier, we see everything
461 done here before the write barrier.
462 */
463
464 assert(_cffi_call_python_org != NULL);
465 _cffi_call_python = (_cffi_call_python_fnptr)_cffi_call_python_org;
466 }
467 else {
468 /* initialization failed. Reset this to NULL, even if it was
469 already set to some other value. Future calls to
470 _cffi_start_python() are still forced to occur, and will
471 always return NULL from now on. */
472 _cffi_call_python_org = NULL;
473 }
474 }
475
476 _cffi_release_reentrant_mutex();
477
478 return (_cffi_call_python_fnptr)_cffi_call_python_org;
479 }
480
481 static
_cffi_start_and_call_python(struct _cffi_externpy_s * externpy,char * args)482 void _cffi_start_and_call_python(struct _cffi_externpy_s *externpy, char *args)
483 {
484 _cffi_call_python_fnptr fnptr;
485 int current_err = errno;
486 #ifdef _MSC_VER
487 int current_lasterr = GetLastError();
488 #endif
489 fnptr = _cffi_start_python();
490 if (fnptr == NULL) {
491 fprintf(stderr, "function %s() called, but initialization code "
492 "failed. Returning 0.\n", externpy->name);
493 memset(args, 0, externpy->size_of_result);
494 }
495 #ifdef _MSC_VER
496 SetLastError(current_lasterr);
497 #endif
498 errno = current_err;
499
500 if (fnptr != NULL)
501 fnptr(externpy, args);
502 }
503
504
505 /* The cffi_start_python() function makes sure Python is initialized
506 and our cffi module is set up. It can be called manually from the
507 user C code. The same effect is obtained automatically from any
508 dll-exported ``extern "Python"`` function. This function returns
509 -1 if initialization failed, 0 if all is OK. */
510 _CFFI_UNUSED_FN
cffi_start_python(void)511 static int cffi_start_python(void)
512 {
513 if (_cffi_call_python == &_cffi_start_and_call_python) {
514 if (_cffi_start_python() == NULL)
515 return -1;
516 }
517 cffi_read_barrier();
518 return 0;
519 }
520
521 #undef cffi_compare_and_swap
522 #undef cffi_write_barrier
523 #undef cffi_read_barrier
524
525 #ifdef __cplusplus
526 }
527 #endif
528