Skip to content

Commit df3b637

Browse files
committed
Add "fork" feature flag (off by default)
1 parent 93fbe4f commit df3b637

17 files changed

Lines changed: 86 additions & 80 deletions

File tree

‎Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ flame-it = ["rustpython-vm/flame-it", "rustpython-stdlib/flame-it", "flame", "fl
2121
freeze-stdlib = ["stdlib", "rustpython-vm/freeze-stdlib", "rustpython-pylib?/freeze-stdlib"]
2222
jit = ["rustpython-vm/jit"]
2323
threading = ["rustpython-vm/threading", "rustpython-stdlib/threading"]
24+
fork = ["rustpython-vm/fork", "rustpython-stdlib/fork"]
2425
sqlite = ["rustpython-stdlib/sqlite"]
2526
ssl = ["host_env"]
2627
ssl-rustls = ["ssl", "rustpython-stdlib/ssl-rustls"]

‎crates/stdlib/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ default = ["compiler", "host_env"]
1515
host_env = ["rustpython-vm/host_env"]
1616
compiler = ["rustpython-vm/compiler"]
1717
threading = ["rustpython-common/threading", "rustpython-vm/threading"]
18+
fork = ["rustpython-vm/fork"]
1819
sqlite = ["dep:libsqlite3-sys"]
1920
# SSL backends
2021
ssl = ["host_env"]

‎crates/stdlib/src/_asyncio.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ pub(crate) mod _asyncio {
4848
});
4949

5050
// Register fork handler to clear task state in child process
51-
#[cfg(unix)]
51+
#[cfg(feature = "fork")]
5252
{
5353
let on_fork = vm
5454
.get_attribute_opt(module.to_owned().into(), vm.ctx.intern_str("_on_fork"))?

‎crates/vm/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ flame-it = ["flame", "flamer"]
2020
freeze-stdlib = ["encodings"]
2121
jit = ["rustpython-jit"]
2222
threading = ["rustpython-common/threading"]
23+
fork = ["threading"]
2324
gc = []
2425
compiler = ["parser", "codegen", "rustpython-compiler"]
2526
ast = ["ruff_python_ast", "ruff_text_size"]

‎crates/vm/src/codecs.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ impl CodecsRegistry {
158158
/// # Safety
159159
/// Must only be called after fork() in the child process when no other
160160
/// threads exist.
161-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
161+
#[cfg(feature = "fork")]
162162
pub(crate) unsafe fn reinit_after_fork(&self) {
163163
unsafe { crate::common::lock::reinit_rwlock_after_fork(&self.inner) };
164164
}

‎crates/vm/src/gc_state.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ impl GcGeneration {
125125
/// # Safety
126126
/// Must only be called after fork() in the child process when no other
127127
/// threads exist.
128-
#[cfg(all(unix, feature = "threading"))]
128+
#[cfg(feature = "fork")]
129129
unsafe fn reinit_stats_after_fork(&self) {
130130
unsafe { crate::common::lock::reinit_mutex_after_fork(&self.stats) };
131131
}
@@ -835,7 +835,7 @@ impl GcState {
835835
/// # Safety
836836
/// Must only be called after fork() in the child process when no other
837837
/// threads exist. The calling thread must NOT hold any of these locks.
838-
#[cfg(all(unix, feature = "threading"))]
838+
#[cfg(feature = "fork")]
839839
pub unsafe fn reinit_after_fork(&self) {
840840
use crate::common::lock::{reinit_mutex_after_fork, reinit_rwlock_after_fork};
841841

‎crates/vm/src/intern.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl StringPool {
3636
/// # Safety
3737
/// Must only be called after fork() in the child process when no other
3838
/// threads exist.
39-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
39+
#[cfg(feature = "fork")]
4040
pub(crate) unsafe fn reinit_after_fork(&self) {
4141
unsafe { crate::common::lock::reinit_rwlock_after_fork(&self.inner) };
4242
}

‎crates/vm/src/object/core.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,7 @@ mod weakref_lock {
474474

475475
/// Reset all weakref stripe locks after fork in child process.
476476
/// Locks held by parent threads would cause infinite spin in the child.
477-
#[cfg(all(unix, feature = "host_env"))]
477+
#[cfg(feature = "fork")]
478478
pub(crate) fn reset_all_after_fork() {
479479
for lock in &LOCKS {
480480
lock.store(0, Ordering::Release);
@@ -497,7 +497,7 @@ mod weakref_lock {
497497

498498
/// Reset weakref stripe locks after fork. Must be called before any
499499
/// Python code runs in the child process.
500-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
500+
#[cfg(feature = "fork")]
501501
pub(crate) fn reset_weakref_locks_after_fork() {
502502
weakref_lock::reset_all_after_fork();
503503
}

‎crates/vm/src/signal.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ pub(crate) fn is_triggered() -> bool {
112112

113113
/// Reset all signal trigger state after fork in child process.
114114
/// Stale triggers from the parent must not fire in the child.
115-
#[cfg(all(unix, feature = "host_env"))]
115+
#[cfg(feature = "fork")]
116116
pub(crate) fn clear_after_fork() {
117117
ANY_TRIGGERED.store(false, Ordering::Release);
118118
for trigger in &TRIGGERS {

‎crates/vm/src/stdlib/_imp.rs‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ mod lock {
3838
IMP_LOCK.lock();
3939
}
4040

41-
#[cfg(all(unix, feature = "host_env"))]
41+
#[cfg(feature = "fork")]
4242
pub(super) fn release_lock_after_fork_parent() {
4343
if IMP_LOCK.is_locked() && IMP_LOCK.is_owned_by_current_thread() {
4444
unsafe { IMP_LOCK.unlock() };
@@ -54,7 +54,7 @@ mod lock {
5454
/// # Safety
5555
///
5656
/// Must only be called from single-threaded child after fork().
57-
#[cfg(all(unix, feature = "host_env"))]
57+
#[cfg(feature = "fork")]
5858
pub(crate) unsafe fn reinit_after_fork() {
5959
if IMP_LOCK.is_locked() && !IMP_LOCK.is_owned_by_current_thread() {
6060
// Held by a dead thread — reset to unlocked.
@@ -66,7 +66,7 @@ mod lock {
6666
/// behavior in the post-fork child:
6767
/// 1) if ownership metadata is stale (dead owner / changed tid), reset;
6868
/// 2) if current thread owns the lock, release it.
69-
#[cfg(all(unix, feature = "host_env"))]
69+
#[cfg(feature = "fork")]
7070
pub(super) unsafe fn after_fork_child_reinit_and_release() {
7171
unsafe { reinit_after_fork() };
7272
if IMP_LOCK.is_locked() && IMP_LOCK.is_owned_by_current_thread() {
@@ -76,22 +76,22 @@ mod lock {
7676
}
7777

7878
/// Re-export for fork safety code in posix.rs
79-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
79+
#[cfg(feature = "fork")]
8080
pub(crate) fn acquire_imp_lock_for_fork() {
8181
lock::acquire_lock_for_fork();
8282
}
8383

84-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
84+
#[cfg(feature = "fork")]
8585
pub(crate) fn release_imp_lock_after_fork_parent() {
8686
lock::release_lock_after_fork_parent();
8787
}
8888

89-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
89+
#[cfg(feature = "fork")]
9090
pub(crate) unsafe fn reinit_imp_lock_after_fork() {
9191
unsafe { lock::reinit_after_fork() }
9292
}
9393

94-
#[cfg(all(unix, feature = "threading", feature = "host_env"))]
94+
#[cfg(feature = "fork")]
9595
pub(crate) unsafe fn after_fork_child_imp_lock_release() {
9696
unsafe { lock::after_fork_child_reinit_and_release() }
9797
}

0 commit comments

Comments
 (0)