Skip to content
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

[TPython] Make TPython thread-safe #16427

Merged
merged 4 commits into from
Sep 17, 2024

Conversation

guitargeek
Copy link
Contributor

The PyGILState_Ensure() and PyGILState_Release() functions should be used as part of idiomatic code that calls Python from a C/C++ thread:

https://docs.python.org/3/c-api/init.html#non-python-created-threads

This addresses the following issue reported by the Gaudi framework developers:
https://gitlab.cern.ch/gaudi/Gaudi/-/issues/329#note_8433064

Copy link

github-actions bot commented Sep 13, 2024

Test Results

    13 files      13 suites   3d 4h 25m 34s ⏱️
 3 032 tests  3 032 ✅ 0 💤 0 ❌
33 895 runs  33 895 ✅ 0 💤 0 ❌

Results for commit b371183.

♻️ This comment has been updated with latest results.

Copy link
Collaborator

@aaronj0 aaronj0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@guitargeek
Copy link
Contributor Author

I have successfully made the following ROOT macro work:

void task1(int i)
{
    std::stringstream code;
    code << "print(" << i << ")";
    TPython::Exec(code.str().c_str());
}

void repro()
{
    int nThreads = 1000;

    std::vector<std::thread> threads;
    for (int i = 0; i < nThreads; i++) {
       threads.emplace_back(task1, i);
    }

    for (int i = 0; i < threads.size(); i++) {
       threads[i].join();
    }
}

I'll turn this into a unit test tomorrow.

@guitargeek guitargeek changed the title [PyROOT] Acquire GIL in TPython [PyROOT] Make TPython thread-safe Sep 17, 2024
guitargeek added a commit to guitargeek/CPyCppyy that referenced this pull request Sep 17, 2024
No static `gPythonizations` variable to avoid static initialization
order fiasco. This avoids some crashes when using `TPython` in compiled
code.

This is necessary to make a newly suggested TPython multithreading unit
test work:
root-project/root#16427
@guitargeek guitargeek force-pushed the tpython_gil branch 2 times, most recently from b7041b6 to aa5ada6 Compare September 17, 2024 08:37
Analogous to commit 2b64c0f, where the same was done in the CPyCppyy
API.
No static `gPythonizations` variable to avoid static initialization
order fiasco. This avoids some crashes when using `TPython` in compiled
code.
The PyGILState_Ensure() and PyGILState_Release() functions should be
used as part of idiomatic code that calls Python from a C/C++ thread:

https://docs.python.org/3/c-api/init.html#non-python-created-threads

Also prevent concurrently initializing the Python interpreter by putting
a lock in the private `TPython::Initialise()` function.

This addresses the following issue reported by the Gaudi framework
developers:
https://gitlab.cern.ch/gaudi/Gaudi/-/issues/329#note_8433064
One would need to acquire the GIL at destruction time to make this work
in multithreading setups.
@guitargeek guitargeek changed the title [PyROOT] Make TPython thread-safe [TPython] Make TPython thread-safe Sep 17, 2024
@guitargeek guitargeek merged commit 43af7f1 into root-project:master Sep 17, 2024
17 of 18 checks passed
@guitargeek guitargeek deleted the tpython_gil branch September 17, 2024 14:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants