diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp')
-rw-r--r-- | venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp | 172 |
1 files changed, 0 insertions, 172 deletions
diff --git a/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp b/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp deleted file mode 100644 index 0d28efd..0000000 --- a/venv/lib/python3.11/site-packages/greenlet/greenlet_cpython_add_pending.hpp +++ /dev/null @@ -1,172 +0,0 @@ -#ifndef GREENLET_CPYTHON_ADD_PENDING_HPP -#define GREENLET_CPYTHON_ADD_PENDING_HPP - -#if (PY_VERSION_HEX >= 0x30800A0 && PY_VERSION_HEX < 0x3090000) && !(defined(_WIN32) || defined(WIN32)) -// XXX: From Python 3.8a3 [1] up until Python 3.9a6 [2][3], -// ``Py_AddPendingCall`` would try to produce a Python exception if -// the interpreter was in the beginning of shutting down when this -// function is called. However, ``Py_AddPendingCall`` doesn't require -// the GIL, and we are absolutely not holding it when we make that -// call. That means that trying to create the Python exception is -// using the C API in an undefined state; here the C API detects this -// and aborts the process with an error ("Fatal Python error: Python -// memory allocator called without holding the GIL": Add -> -// PyErr_SetString -> PyUnicode_New -> PyObject_Malloc). This arises -// (obviously) in multi-threaded programs and happens if one thread is -// exiting and cleaning up its thread-local data while the other -// thread is trying to shut down the interpreter. A crash on shutdown -// is still a crash and could result in data loss (e.g., daemon -// threads are still running, pending signal handlers may be present, -// buffers may not be flushed, there may be __del__ that need run, -// etc), so we have to work around it. -// -// Of course, we can (and do) check for whether the interpreter is -// shutting down before calling ``Py_AddPendingCall``, but that's a -// race condition since we don't hold the GIL, and so we may not -// actually get the right answer. Plus, ``Py_FinalizeEx`` actually -// calls ``_Py_FinishPendingCalls`` (which sets the pending->finishing -// flag, which is used to gate creating the exceptioen) *before* -// publishing any other data that would let us detect the shutdown -// (such as runtime->finalizing). So that point is moot. -// -// Our solution for those versions is to inline the same code, without -// the problematic bit that sets the exception. Unfortunately, all of -// the structure definitions are private/opaque, *and* we can't -// actually count on being able to include their definitions from -// ``internal/pycore_*``, because on some platforms those header files -// are incomplete (i.e., on macOS with macports 3.8, the includes are -// fine, but on Ubuntu jammy with 3.8 from ppa:deadsnakes or GitHub -// Actions 3.8 (I think it's Ubuntu 18.04), they con't be used; at -// least, I couldn't get them to work). So we need to define the -// structures and _PyRuntime data member ourself. Yet more -// unfortunately, _PyRuntime won't link on Windows, so we can only do -// this on other platforms. -// -// [1] https://github.com/python/cpython/commit/842a2f07f2f08a935ef470bfdaeef40f87490cfc -// [2] https://github.com/python/cpython/commit/cfc3c2f8b34d3864717ab584c5b6c260014ba55a -// [3] https://github.com/python/cpython/issues/81308 -# define GREENLET_BROKEN_PY_ADD_PENDING 1 - -// When defining these structures, the important thing is to get -// binary compatibility, i.e., structure layout. For that, we only -// need to define fields up to the ones we use; after that they're -// irrelevant UNLESS the structure is included in another structure -// *before* the structure we're interested in --- in that case, it -// must be complete. Ellipsis indicate elided trailing members. -// Pointer types are changed to void* to keep from having to define -// more structures. - -// From "internal/pycore_atomic.h" - -// There are several different definitions of this, including the -// plain ``int`` version, a ``volatile int`` and an ``_Atomic int`` -// I don't think any of those change the size/layout. -typedef struct _Py_atomic_int { - volatile int _value; -} _Py_atomic_int; - -// This needs too much infrastructure, so we just do a regular store. -#define _Py_atomic_store_relaxed(ATOMIC_VAL, NEW_VAL) \ - (ATOMIC_VAL)->_value = NEW_VAL - - - -// From "internal/pycore_pymem.h" -#define NUM_GENERATIONS 3 - - -struct gc_generation { - PyGC_Head head; // We already have this defined. - int threshold; - int count; -}; -struct gc_generation_stats { - Py_ssize_t collections; - Py_ssize_t collected; - Py_ssize_t uncollectable; -}; - -struct _gc_runtime_state { - void *trash_delete_later; - int trash_delete_nesting; - int enabled; - int debug; - struct gc_generation generations[NUM_GENERATIONS]; - void *generation0; - struct gc_generation permanent_generation; - struct gc_generation_stats generation_stats[NUM_GENERATIONS]; - int collecting; - void *garbage; - void *callbacks; - Py_ssize_t long_lived_total; - Py_ssize_t long_lived_pending; -}; - -// From "internal/pycore_pystate.h" -struct _pending_calls { - int finishing; - PyThread_type_lock lock; - _Py_atomic_int calls_to_do; - int async_exc; -#define NPENDINGCALLS 32 - struct { - int (*func)(void *); - void *arg; - } calls[NPENDINGCALLS]; - int first; - int last; -}; - -struct _ceval_runtime_state { - int recursion_limit; - int tracing_possible; - _Py_atomic_int eval_breaker; - _Py_atomic_int gil_drop_request; - struct _pending_calls pending; - // ... -}; - -typedef struct pyruntimestate { - int preinitializing; - int preinitialized; - int core_initialized; - int initialized; - void *finalizing; - - struct pyinterpreters { - PyThread_type_lock mutex; - void *head; - void *main; - int64_t next_id; - } interpreters; - // XXX Remove this field once we have a tp_* slot. - struct _xidregistry { - PyThread_type_lock mutex; - void *head; - } xidregistry; - - unsigned long main_thread; - -#define NEXITFUNCS 32 - void (*exitfuncs[NEXITFUNCS])(void); - int nexitfuncs; - - struct _gc_runtime_state gc; - struct _ceval_runtime_state ceval; - // ... -} _PyRuntimeState; - -#define SIGNAL_PENDING_CALLS(ceval) \ - do { \ - _Py_atomic_store_relaxed(&(ceval)->pending.calls_to_do, 1); \ - _Py_atomic_store_relaxed(&(ceval)->eval_breaker, 1); \ - } while (0) - -extern _PyRuntimeState _PyRuntime; - -#else -# define GREENLET_BROKEN_PY_ADD_PENDING 0 -#endif - - -#endif |