GeezerVison is showing github.com — force_unlock_after_fork by youknowone · Pull Request #7186 · RustPython/RustPython
Conversation
youknowone
commented
Feb 17, 2026
•
edited by coderabbitai
Bot
Loading
Uh oh!
There was an error while loading. Please reload this page.
Summary by CodeRabbit
-
Chores
- Enhanced fork handling to prevent potential deadlocks by ensuring proper cleanup of internal locks after process forking, improving stability in multi-threaded scenarios.
-
Style
- Minor formatting improvements.
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
coderabbitai
Bot
commented
Feb 17, 2026
•
edited
Loading
Uh oh!
There was an error while loading. Please reload this page.
|
No actionable comments were generated in the recent review. 🎉
📝 Walkthrough
Walkthrough
This PR adds post-fork unlock mechanisms to prevent deadlocks in child processes. It introduces unsafe force_unlock_after_fork() methods on CodecsRegistry and StringPool, then uses them to unlock various global VM state locks in the POSIX fork handler. Thread cleanup logic is updated to forcefully release locks when needed before proceeding with cleanup operations.
Changes
| Cohort / File(s) |
Summary |
Lock/Registry Force-Unlock Methods crates/vm/src/codecs.rs, crates/vm/src/intern.rs |
Add unsafe force_unlock_after_fork() methods to CodecsRegistry and StringPool that repeatedly unlock read locks or forcefully unlock write locks held by dead threads until a write lock can be acquired. |
Post-Fork Lock Cleanup crates/vm/src/stdlib/posix.rs |
Introduces unsafe helper to force-unlock PyMutex instances and calls it on string pool, codec registry, atexit funcs, fork-related thread lists, and global trace/profile state after fork. Replaces try_lock fallback with direct lock-and-clone for after_forkers_child. |
Thread Handle Cleanup crates/vm/src/stdlib/thread.rs |
Updates thread_handles and shutdown_handles cleanup in after_fork_child to check if locks are held via try_lock, force-unlock if needed, then proceed with guarded cleanup that marks non-current threads as Done and notifies waiters when possible. |
Formatting crates/vm/src/stdlib/sys.rs |
Minor single-line formatting adjustment to excepthook binding; no functional changes. |
Sequence Diagram
sequenceDiagram
participant Parent as Parent Process
participant Fork as Fork Operation
participant Child as Child Process
participant Locks as VM State Locks
participant Cleanup as Cleanup Handler
Parent->>Fork: Call fork()
Fork->>Child: Create child, copy memory/locks
Fork-->>Parent: Return to parent
Child->>Cleanup: Begin child initialization
Cleanup->>Locks: Check if write lock available (try_lock)
alt Lock held by dead thread
Cleanup->>Locks: force_unlock_after_fork()
Locks->>Locks: Repeatedly unlock read locks
Locks->>Locks: Or force unlock write lock
Locks->>Locks: Acquire clean write lock
else Lock available
Locks-->>Cleanup: Write lock acquired
end
Cleanup->>Locks: Unlock and proceed
Cleanup->>Child: Resume child execution
Loading
Estimated code review effort
🎯 3 (Moderate) | ⏱️ ~25 minutes
Possibly related PRs
- Use try_lock in py_os_after_fork_child #7178: Modifies after-fork child handling in posix.py around acquiring the after_forkers_child lock; this PR replaces its try_lock fallback with forced unlocking and direct clone semantics.
- clear_after_fork #6933: Modifies Unix child-after-fork initialization in posix.rs to reset global VM state; this PR adds complementary force-unlock logic for various mutexed registries in the same path.
- Fix ssl shutdown #6871: Updates after_fork_child logic in thread.rs for shutdown_handles cleanup; this PR extends that function with force-unlock patterns for both thread_handles and shutdown_handles.
Poem
🐰 After the fork, the locks do run,
But child threads are gone, leaving locks undone.
With force_unlock() we set them free,
No deadlock haunts the child, wheee! 🎉
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
| Check name |
Status |
Explanation |
| Description Check |
✅ Passed |
Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check |
✅ Passed |
The title 'force_unlock_after_fork' directly and clearly describes the primary change: adding force_unlock_after_fork methods across multiple lock types (CodecsRegistry, StringPool) and their integration into the fork child cleanup paths. |
| Docstring Coverage |
✅ Passed |
Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing Touches
🧪 Generate unit tests (beta)
- Create PR with unit tests
- Post copyable unit tests in a comment
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
❤️ Share
Comment @coderabbitai help to get the list of available commands and usage tips.
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
|
Code has been automatically formatted
The code in this PR has been formatted using:
cargo fmt --all
Please pull the latest changes before pushing again:
git pull origin after-fork
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
📦 Library Dependencies
The following Lib/ modules were modified. Here are their dependencies:
[ ] lib: cpython/Lib/ctypes
[ ] test: cpython/Lib/test/test_ctypes (TODO: 17)
[x] test: cpython/Lib/test/test_stable_abi_ctypes.py
dependencies:
- ctypes (native: _ctypes, ctypes._endian, ctypes.macholib.dylib, ctypes.macholib.framework, itertools, sys)
- subprocess (native: builtins, errno, sys, time)
- sysconfig (native: os.path, sys)
- types
- os, re, shutil, struct, warnings
dependent tests: (1 tests)
[x] lib: cpython/Lib/inspect.py
[ ] test: cpython/Lib/test/test_inspect (TODO: 48)
dependencies:
dependent tests: (45 tests)
- inspect: test_abc test_argparse test_asyncgen test_buffer test_builtin test_code test_collections test_coroutines test_decimal test_enum test_functools test_generators test_grammar test_inspect test_ntpath test_operator test_patma test_posixpath test_pydoc test_signal test_traceback test_type_annotations test_types test_typing test_unittest test_yield_from test_zipimport
- asyncio: test_asyncio test_contextlib_async test_logging test_os test_sys_settrace test_unittest
- bdb: test_bdb
- dataclasses: test__colorize test_ctypes test_genericalias test_pprint test_regrtest test_zoneinfo
- importlib.metadata: test_importlib
- pydoc:
- xmlrpc.server: test_docxmlrpc test_xmlrpc
- rlcompleter: test_rlcompleter
- trace: test_trace
[ ] lib: cpython/Lib/multiprocessing
[ ] test: cpython/Lib/test/test_multiprocessing_fork (TODO: 35)
[ ] test: cpython/Lib/test/test_multiprocessing_forkserver (TODO: 10)
[ ] test: cpython/Lib/test/test_multiprocessing_spawn (TODO: 13)
[x] test: cpython/Lib/test/test_multiprocessing_main_handling.py
dependencies:
- multiprocessing (native: _multiprocessing, _winapi, array, atexit, collections.abc, errno, itertools, mmap, msvcrt, sys, time)
- collections (native: _weakref, itertools, sys)
- json (native: json.tool, sys)
- pickle (native: itertools, sys)
- tempfile (native: _thread, errno, sys)
- ctypes, subprocess, types
- _weakrefset, abc, base64, bisect, copyreg, functools, io, os, queue, runpy, secrets, selectors, signal, socket, struct, threading, traceback, warnings, weakref
dependent tests: (5 tests)
- multiprocessing: test_asyncio test_concurrent_futures test_fcntl test_multiprocessing_main_handling
- concurrent.futures.process: test_concurrent_futures
[ ] lib: cpython/Lib/collections
[x] lib: cpython/Lib/_collections_abc.py
[x] test: cpython/Lib/test/test_collections.py (TODO: 3)
[x] test: cpython/Lib/test/test_deque.py (TODO: 3)
[x] test: cpython/Lib/test/test_defaultdict.py (TODO: 1)
[ ] test: cpython/Lib/test/test_ordered_dict.py (TODO: 4)
dependencies:
dependent tests: (196 tests)
- collections: test_annotationlib test_array test_asyncio test_bisect test_builtin test_c_locale_coercion test_call test_collections test_configparser test_contains test_csv test_ctypes test_defaultdict test_deque test_dict test_dictviews test_enum test_exception_group test_file test_fileinput test_fileio test_functools test_genericalias test_hash test_httpservers test_inspect test_io test_ipaddress test_iter test_iterlen test_json test_ordered_dict test_pathlib test_patma test_pickle test_plistlib test_pprint test_pydoc test_random test_set test_shelve test_sqlite3 test_statistics test_string test_struct test_traceback test_types test_typing test_unittest test_urllib test_userdict test_userlist test_userstring test_weakref test_weakset test_with
- asyncio: test_asyncio test_contextlib_async test_logging test_os test_sys_settrace test_unittest
- concurrent.futures._base: test_concurrent_futures
- dbm.dumb: test_dbm_dumb
- dbm.sqlite3: test_dbm_sqlite3
- difflib: test_difflib
- dis: test__opcode test_ast test_code test_compile test_compiler_assemble test_dis test_dtrace test_fstring test_opcache test_peepholer test_positional_only_arg
- inspect: test_abc test_argparse test_asyncgen test_buffer test_coroutines test_decimal test_generators test_grammar test_ntpath test_operator test_posixpath test_signal test_type_annotations test_yield_from test_zipimport
- trace: test_trace
- http.client: test_docxmlrpc test_hashlib test_ssl test_ucn test_unicodedata test_urllib2 test_wsgiref test_xmlrpc
- urllib.request: test_http_cookiejar test_site test_urllib2_localnet test_urllib2net test_urllibnet
- importlib.metadata: test_importlib test_zoneinfo
- inspect:
- bdb: test_bdb
- dataclasses: test__colorize test_ctypes test_regrtest
- rlcompleter: test_rlcompleter
- multiprocessing: test_concurrent_futures test_fcntl test_multiprocessing_main_handling
- pkgutil: test_pkgutil
- platform: test__locale test__osx_support test_android test_baseexception test_cmath test_ctypes test_math test_mimetypes test_platform test_posix test_socket test_sysconfig test_time test_winreg
- pprint: test_htmlparser test_sys_setprofile
- queue: test_concurrent_futures test_dummy_thread test_sched
- selectors: test_selectors test_subprocess
- socketserver: test_imaplib test_socketserver
- shutil: test_bz2 test_compileall test_ctypes test_filecmp test_glob test_importlib test_largefile test_launcher test_py_compile test_reprlib test_shutil test_string_literals test_support test_tempfile test_venv
- ctypes.util: test_ctypes
- ensurepip: test_ensurepip
- tarfile: test_tarfile
- tempfile: test_bytes test_cmd_line test_contextlib test_doctest test_faulthandler test_importlib test_linecache test_mailbox test_pkg test_runpy test_tabnanny test_termios test_threadedtempfile test_tomllib test_urllib_response test_winconsoleio test_zipapp test_zipfile test_zipfile64 test_zstd
- webbrowser: test_webbrowser
- zipfile: test_zipfile
- tokenize: test_tokenize test_unparse
- traceback: test_code_module test_dictcomps test_importlib test_listcomps test_pyexpat test_setcomps test_threading test_unittest
- traceback:
- py_compile: test_cmd_line_script test_importlib
- urllib.parse: test_sqlite3 test_urlparse
- urllib.robotparser: test_robotparser
- wave: test_wave
Legend:
[+] path exists in CPython
[x] up-to-date, [ ] outdated
|
Sorry, something went wrong.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
This was referenced Mar 2, 2026
Uh oh!
There was an error while loading. Please reload this page.
Assignees
No one assigned
Milestone
No milestone
Development
Successfully merging this pull request may close these issues.
Uh oh!
There was an error while loading. Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
|