-
Notifications
You must be signed in to change notification settings - Fork 2.2k
fix: don't destruct module objects in atexit #5688
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
… for every interpreter.
…his be removed` The TODO was introduced with: pybind@7800e7f
I pushed another cleanup commit. I overlooked that part before. The CI to watch is: https://github.com/pybind/pybind11/actions/runs/15230269745 EDIT: The CI run for commit 8736e1a succeeded (after one round of deflaking). |
@b-pass, see my last three question. Could you please help me getting my head around: What exactly happens in that code when there are sub-interpreters? What variables should be |
Unrelated to this PR: @henryiii there was this flake: https://github.com/pybind/pybind11/actions/runs/15230269745/job/42837274697 Not sure if you want to keep track? (I just triggered a rerun.) EDIT: The rerun succeeded: https://github.com/pybind/pybind11/actions/runs/15230269745/job/42837982511 |
Sub-interpreters rerun PyInit_ the first time the module is imported in the sub-interpreter. That could (and we have a test that does) happen in multiple threads at the same time. Everything here should be static. The only non-static step is running The resulting PyObject should, IMO, be treated like any other Pyobject which means it should not be used across interpreters. However, it would be safe to do so based on the current implementation of |
Do you think it would make sense to distill this into a comment? (I'm not sure what's the best place to put it.) |
- Get rid of initialize_multiphase_module_def and just initialize it here in the function. - Make a simple slots init - Mkae these function statics instead of globals - Get rid of the lambda and just use the PyModuleDef member initializer.
I'm tracking flakes in #5674. Those tests were intended to test the GIL, have so far resisted temptation to just skip them in free-threading. They need a lock somewhere. If someone has an idea, let me know. :) I haven't been able to recreate these errors locally; I've tried the pytest free threading plugin, increasing the number of threads, and changing timeouts. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very nice, thanks a lot for the cleanup! Looks good to me, just one small oversight, and a question.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, this didn't send earlier.
@@ -1438,19 +1477,16 @@ class module_ : public object { | |||
PyModule_AddObject(ptr(), name, obj.inc_ref().ptr() /* steals a reference */); | |||
} | |||
|
|||
using module_def = PyModuleDef; // TODO: Can this be removed (it was needed only for Python 2)? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While this isn't heavily used, it is used, so maybe we should keep it around just a little longer? Especially since we are in the RC phase?
Longer term, we have a collection of these defines used for Py2 compatibility, and it would be really nice to list them as deprecated and ideally make using them produce a deprecation warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for catching this! I'll put it back, with a deprecation comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done: commit 93d093c
I tried using PYBIND11_DEPRECATED
but unfortunately that doesn't work:
https://chatgpt.com/share/683351d0-14a8-8008-9d31-0fd287dfc198
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Description
Likely fix for #5687.
The module objects created by MODULE_INIT macros are stored in static
pybind11::object
, which will try to DECREF them when the program exits, which is likely to crash because the interpreter has probably shut down by then.The solution is to just store the pointer, so that there is nothing to destruct during
atexit
.📚 Documentation preview 📚: https://pybind11--5688.org.readthedocs.build/