const char* _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, PyThreadState *current_thread) { PyThreadState *tstate; unsigned int nthreads; /* Get the current interpreter from the current thread */ tstate = PyInterpreterState_ThreadHead(interp); if (tstate == NULL) return "unable to get the thread head state"; /* Dump the traceback of each thread */ tstate = PyInterpreterState_ThreadHead(interp); nthreads = 0; do { if (nthreads != 0) write(fd, "\n", 1); if (nthreads >= MAX_NTHREADS) { PUTS(fd, "...\n"); break; } write_thread_id(fd, tstate, tstate == current_thread); dump_traceback(fd, tstate, 0); tstate = PyThreadState_Next(tstate); nthreads++; } while (tstate != NULL); return NULL; }
static void _enum_threads(_ctx* (*f) (PyThreadState *)) { PyThreadState *ts; PyInterpreterState* is; for(is=PyInterpreterState_Head();is!=NULL;is = PyInterpreterState_Next(is)) { for (ts=PyInterpreterState_ThreadHead(is) ; ts != NULL; ts = ts->next) { f(ts); } } }
static void local_dealloc(localobject *self) { PyThreadState *tstate; if (self->key && (tstate = PyThreadState_Get()) && tstate->interp) { for(tstate = PyInterpreterState_ThreadHead(tstate->interp); tstate; tstate = PyThreadState_Next(tstate)) if (tstate->dict && PyDict_GetItem(tstate->dict, self->key)) PyDict_DelItem(tstate->dict, self->key); } local_clear(self); Py_TYPE(self)->tp_free((PyObject*)self); }
void _PyInterpreterState_IDDecref(PyInterpreterState *interp) { if (interp->id_mutex == NULL) { return; } PyThread_acquire_lock(interp->id_mutex, WAIT_LOCK); assert(interp->id_refcount != 0); interp->id_refcount -= 1; int64_t refcount = interp->id_refcount; PyThread_release_lock(interp->id_mutex); if (refcount == 0 && interp->requires_idref) { // XXX Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); // XXX Possible GILState issues? PyThreadState *save_tstate = PyThreadState_Swap(tstate); Py_EndInterpreter(tstate); PyThreadState_Swap(save_tstate); } }
static void _call_in_interpreter(PyInterpreterState *interp, void (*func)(void *), void *arg) { /* We would use Py_AddPendingCall() if it weren't specific to the * main interpreter (see bpo-33608). In the meantime we take a * naive approach. */ PyThreadState *save_tstate = NULL; if (interp != _PyInterpreterState_Get()) { // XXX Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); // XXX Possible GILState issues? save_tstate = PyThreadState_Swap(tstate); } func(arg); // Switch back. if (save_tstate != NULL) { PyThreadState_Swap(save_tstate); } }
void _PyCrossInterpreterData_Release(_PyCrossInterpreterData *data) { if (data->data == NULL && data->obj == NULL) { // Nothing to release! return; } // Switch to the original interpreter. PyInterpreterState *interp = _PyInterpreterState_LookUpID(data->interp); if (interp == NULL) { // The intepreter was already destroyed. if (data->free != NULL) { // XXX Someone leaked some memory... } return; } PyThreadState *save_tstate = NULL; if (interp != PyThreadState_Get()->interp) { // XXX Using the "head" thread isn't strictly correct. PyThreadState *tstate = PyInterpreterState_ThreadHead(interp); // XXX Possible GILState issues? save_tstate = PyThreadState_Swap(tstate); } // "Release" the data and/or the object. if (data->free != NULL) { data->free(data->data); } Py_XDECREF(data->obj); // Switch back. if (save_tstate != NULL) { PyThreadState_Swap(save_tstate); } }
/* Dump the traceback of all Python threads into fd. Use write() to write the traceback and retry if write() is interrupted by a signal (failed with EINTR), but don't call the Python signal handler. The caller is responsible to call PyErr_CheckSignals() to call Python signal handlers if signals were received. */ const char* _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp, PyThreadState *current_tstate) { PyThreadState *tstate; unsigned int nthreads; if (current_tstate == NULL) { /* _Py_DumpTracebackThreads() is called from signal handlers by faulthandler. SIGSEGV, SIGFPE, SIGABRT, SIGBUS and SIGILL are synchronous signals and are thus delivered to the thread that caused the fault. Get the Python thread state of the current thread. PyThreadState_Get() doesn't give the state of the thread that caused the fault if the thread released the GIL, and so this function cannot be used. Read the thread specific storage (TSS) instead: call PyGILState_GetThisThreadState(). */ current_tstate = PyGILState_GetThisThreadState(); } if (interp == NULL) { if (current_tstate == NULL) { interp = _PyGILState_GetInterpreterStateUnsafe(); if (interp == NULL) { /* We need the interpreter state to get Python threads */ return "unable to get the interpreter state"; } } else { interp = current_tstate->interp; } } assert(interp != NULL); /* Get the current interpreter from the current thread */ tstate = PyInterpreterState_ThreadHead(interp); if (tstate == NULL) return "unable to get the thread head state"; /* Dump the traceback of each thread */ tstate = PyInterpreterState_ThreadHead(interp); nthreads = 0; _Py_BEGIN_SUPPRESS_IPH do { if (nthreads != 0) PUTS(fd, "\n"); if (nthreads >= MAX_NTHREADS) { PUTS(fd, "...\n"); break; } write_thread_id(fd, tstate, tstate == current_tstate); dump_traceback(fd, tstate, 0); tstate = PyThreadState_Next(tstate); nthreads++; } while (tstate != NULL); _Py_END_SUPPRESS_IPH return NULL; }