{"record":{"id":"87f07f318f2a3d6f","repo":"python/cpython","slug":"detach-thread-failed-detaching-thread-n","errorCode":null,"errorMessage":"detach_thread: failed detaching thread\\n","messagePattern":"detach_thread: failed detaching thread\\\\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"Modules/_threadmodule.c","lineNumber":261,"sourceCode":"\n    return self;\n}\n\nstatic void\nThreadHandle_incref(ThreadHandle *self)\n{\n    _Py_atomic_add_ssize(&self->refcount, 1);\n}\n\nstatic int\ndetach_thread(ThreadHandle *self)\n{\n    if (!self->has_os_handle) {\n        return 0;\n    }\n    // This is typically short so no need to release the GIL\n    if (PyThread_detach_thread(self->os_handle)) {\n        fprintf(stderr, \"detach_thread: failed detaching thread\\n\");\n        return -1;\n    }\n    return 0;\n}\n\n// NB: This may be called after the PyThreadState in `thread_run` has been\n// deleted; it cannot call anything that relies on a valid PyThreadState\n// existing.\nstatic void\nThreadHandle_decref(ThreadHandle *self)\n{\n    if (_Py_atomic_add_ssize(&self->refcount, -1) > 1) {\n        return;\n    }\n\n    // Remove ourself from the global list of handles\n    HEAD_LOCK(&_PyRuntime);\n    if (self->node.next != NULL) {","sourceCodeStart":243,"sourceCodeEnd":279,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Modules/_threadmodule.c#L243-L279","documentation":"Diagnostic printed to stderr by the _thread module's ThreadHandle implementation when the underlying OS call to detach a joinable thread fails (non-zero return) during interpreter/thread teardown. It indicates the OS refused to detach — typically because the thread is not in a detachable state — but execution continues; it is a warning-level trace, not a raised exception.","triggerScenarios":"ThreadHandle cleanup at interpreter shutdown or Thread object deallocation calling PyThread_detach_thread() on pthreads whose state is no longer joinable-detachable (already exited and reaped, or detached elsewhere); races between thread exit and handle finalization.","commonSituations":"Heavy multithreaded programs embedding CPython exiting while daemon threads are being torn down; C extensions creating raw pthreads that interact with Python thread handles; observed on platforms with stricter pthread lifecycle enforcement. No Python-level exception is raised.","solutions":["Ensure threads are either joined (thread.join()) or fully detached consistently before interpreter shutdown","Avoid mixing raw pthread_create/detach from extensions with Python _thread handles for the same thread","Upgrade CPython — thread teardown handling in this path has seen fixes across releases","If it only appears at exit with daemon threads, convert critical threads to non-daemon and join them"],"exampleFix":null,"handlingStrategy":"fallback","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Join or explicitly detach every thread before interpreter shutdown","Do not manage the same OS thread from both raw pthreads and _thread handles","Keep daemon threads only for truly disposable work; join critical ones","Track the CPython version — teardown races in this area have been patched over time"],"tags":["threading","cpython","pthreads","interpreter-shutdown"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}