Skip to content

Fix use-after-free of pyState at process exit on Linux - #36

Merged
StephenSmith25 merged 1 commit into
StephenSmith25:masterfrom
SamiAGOURRAM:fix/exit-order-pystate
Nov 5, 2026
Merged

StephenSmith25 merged 1 commit into
StephenSmith25:masterfrom
SamiAGOURRAM:fix/exit-order-pystate

Conversation

@SamiAGOURRAM

Copy link
Copy Markdown
Contributor

Fixes #35.

At process exit on Linux, glibc runs the C++ static destructors (__run_exit_handlers) before the libraries' destructor functions (_dl_fini). The namespace-scope std::shared_ptr<PyState> pyState is therefore already destroyed when onLibraryUnload → finalizePythonInterpreter assigns it nullptr, and that assignment decrements a reference count in freed memory.

This change keeps the state and its mutex in objects that are allocated once and never destroyed (function-local static pointers), so finalizePythonInterpreter always resets a live shared_ptr; it also takes the mutex, as instantiation does. Nothing else changes; the Windows DllMain path is untouched.

Checked:

At exit, glibc runs the C++ static destructors (__run_exit_handlers)
before the libraries' destructor functions (_dl_fini). The
namespace-scope shared_ptr pyState was therefore already destroyed when
onLibraryUnload -> finalizePythonInterpreter assigned it nullptr, and
that assignment decremented a reference count in freed memory,
corrupting the heap (glibc could then abort in a later free).

Keep the state and its mutex in objects that are allocated once and
never destroyed, reached through function-local static pointers, so
finalizePythonInterpreter always resets a live shared_ptr. It also takes
the mutex, as instantiation does.
@StephenSmith25

Copy link
Copy Markdown
Owner

I'll look at this by tomorrow but thanks for reporting the issue and fixing it!

@StephenSmith25
StephenSmith25 merged commit 59f8df6 into StephenSmith25:master Nov 5, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants