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

gh-126688: Reinit import lock after fork #126692

Merged
merged 3 commits into from
Nov 12, 2024

Conversation

colesbury
Copy link
Contributor

@colesbury colesbury commented Nov 11, 2024

The PyMutex implementation supports unlocking after fork because we clear the list of watiers in parking_lot.c. This doesn't work as well for _PyRecursiveMutex because on some systems, such as SerenityOS, the thread id is not preserved across fork().

The PyMutex implementation supports unlocking after fork because we
clear the list of watiers in parking_lot.c. This doesn't work as well
for _PyRecursiveMutex because on some systems, such as SerenityOS, the
thread id is not preserved across fork().
@oskar-skog
Copy link

I can confirm applying the diff from 25aee21 to 27d5db7 to the Python 3.13.0 port in SerenityOS fixes the issue with fork.

@colesbury
Copy link
Contributor Author

Thanks @oskar-skog. My first attempt had a bug and I also had to merge "main" back into the PR branch to fix some other test issues. Sorry if that complicated applying the diff to 3.13.

You may already know this, but you can get the PR as a diff with a URL like https://github.com/python/cpython/pull/126692.patch. That's sometimes easier to apply than diffing between two commits involving merges.

@oskar-skog
Copy link

No, it actually made it simpler to patch, and I didn't know you could just download a PR as a patch.

@colesbury colesbury merged commit 5610860 into python:main Nov 12, 2024
45 checks passed
@miss-islington-app
Copy link

Thanks @colesbury for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13.
🐍🍒⛏🤖 I'm not a witch! I'm not a witch!

@colesbury colesbury deleted the gh-126688-import-lock branch November 12, 2024 20:54
@ambv ambv added needs backport to 3.13 bugs and security fixes and removed needs backport to 3.13 bugs and security fixes labels Nov 12, 2024
@miss-islington-app
Copy link

Thanks @colesbury for the PR 🌮🎉.. I'm working now to backport this PR to: 3.13.
🐍🍒⛏🤖

miss-islington pushed a commit to miss-islington/cpython that referenced this pull request Nov 12, 2024
The PyMutex implementation supports unlocking after fork because we
clear the list of waiters in parking_lot.c. This doesn't work as well
for _PyRecursiveMutex because on some systems, such as SerenityOS, the
thread id is not preserved across fork().
(cherry picked from commit 5610860)

Co-authored-by: Sam Gross <colesbury@gmail.com>
@bedevere-app
Copy link

bedevere-app bot commented Nov 12, 2024

GH-126765 is a backport of this pull request to the 3.13 branch.

@bedevere-app bedevere-app bot removed the needs backport to 3.13 bugs and security fixes label Nov 12, 2024
colesbury added a commit that referenced this pull request Nov 12, 2024
The PyMutex implementation supports unlocking after fork because we
clear the list of waiters in parking_lot.c. This doesn't work as well
for _PyRecursiveMutex because on some systems, such as SerenityOS, the
thread id is not preserved across fork().
(cherry picked from commit 5610860)

Co-authored-by: Sam Gross <colesbury@gmail.com>
Comment on lines +128 to +129
// gh-126688: Thread id may change after fork() on some operating systems.
IMPORT_LOCK(interp).thread = PyThread_get_thread_ident_ex();
Copy link
Member

Choose a reason for hiding this comment

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

Wouldn't this lead to deadlocks if some other thread happened to be holding the import lock when we forked? It seems like the child process needs to know the thread ID from which it forked.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We acquire the import lock before forking so that no other thread holds it:

void
PyOS_BeforeFork(void)
{
PyInterpreterState *interp = _PyInterpreterState_GET();
run_at_forkers(interp->before_forkers, 1);
_PyImport_AcquireLock(interp);

Copy link
Member

Choose a reason for hiding this comment

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

Hmm, looks like we always acquire the import lock in PyOS_BeforeFork(). It should be fine then.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants