python_multiprocessing_lock_works_under_sandbox fails on Python 3.14; Python 3.12 passes

Resolved 💬 5 comments Opened Jan 16, 2026 by ahornby Closed Apr 18, 2026

The test suite::sandbox::python_multiprocessing_lock_works_under_sandbox fails when the system python3 points to 3.14.x, but passes with 3.12.x. The failure occurs during multiprocessing startup and appears to be blocked by the sandbox. Noticed this while trying to run tests locally to validate another change.

Could be this is from python 3.14 defaulting to forkserver which likely needs more sandbox permissions

Reproduced on Fedora 43 x86_64, which has python3 as 3.14, but handily also has a python 3.12 package available.

Example failed test run with 3.14:

$ cargo nextest run --all-features --no-fail-fast suite::sandbox::python_multiprocessing_lock_works_under_sandbox
Fri 16 Jan 2026 19:28:41 GMT
    Finished `test` profile [unoptimized + debuginfo] target(s) in 0.30s
────────────
 Nextest run ID c60e14b5-c4f8-4a4d-9f43-ea822e516d92 with nextest profile: default
    Starting 1 test across 107 binaries (3199 tests skipped)
        FAIL [   0.057s] codex-exec::all suite::sandbox::python_multiprocessing_lock_works_under_sandbox
  stdout ───

    running 1 test
    test suite::sandbox::python_multiprocessing_lock_works_under_sandbox ... FAILED

    failures:

    failures:
        suite::sandbox::python_multiprocessing_lock_works_under_sandbox

    test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 41 filtered out; finished in 0.05s
    
  stderr ───
    Traceback (most recent call last):
      File "<string>", line 9, in <module>
        lock = Lock()
      File "/usr/lib64/python3.14/multiprocessing/context.py", line 68, in Lock
        return Lock(ctx=self.get_context())
      File "/usr/lib64/python3.14/multiprocessing/synchronize.py", line 176, in __init__
        SemLock.__init__(self, SEMAPHORE, 1, 1, ctx=ctx)
        ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/usr/lib64/python3.14/multiprocessing/synchronize.py", line 79, in __init__
        register(self._semlock.name, "semaphore")
        ~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/usr/lib64/python3.14/multiprocessing/resource_tracker.py", line 268, in register
        self._send('REGISTER', name, rtype)
        ~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/usr/lib64/python3.14/multiprocessing/resource_tracker.py", line 285, in _send
        self._ensure_running_and_write(msg)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^
      File "/usr/lib64/python3.14/multiprocessing/resource_tracker.py", line 253, in _ensure_running_and_write
        self._write(msg)
        ~~~~~~~~~~~^^^^^
      File "/usr/lib64/python3.14/multiprocessing/resource_tracker.py", line 275, in _write
        nbytes = os.write(self._fd, msg)
    BrokenPipeError: [Errno 32] Broken pipe

    thread 'suite::sandbox::python_multiprocessing_lock_works_under_sandbox' panicked at exec/tests/suite/sandbox.rs:111:5:
    python exited with ExitStatus(unix_wait_status(256))
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

────────────
     Summary [   0.067s] 1 test run: 0 passed, 1 failed, 3199 skipped
        FAIL [   0.057s] codex-exec::all suite::sandbox::python_multiprocessing_lock_works_under_sandbox
error: test run failed

If sudo dnf install python3.12 and force the failing test to python3.12 as below it works:

diff --git a/codex-rs/exec/tests/suite/sandbox.rs b/codex-rs/exec/tests/suite/sandbox.rs
index 303023b1..4dccf672 100644
--- a/codex-rs/exec/tests/suite/sandbox.rs
+++ b/codex-rs/exec/tests/suite/sandbox.rs
@@ -94,7 +94,7 @@ if __name__ == '__main__':
     let sandbox_cwd = command_cwd.clone();
     let mut child = spawn_command_under_sandbox(
         vec![
-            "python3".to_string(),
+            "python3.12".to_string(),
             "-c".to_string(),
             python_code.to_string(),
         ],

Which then works:

$ cargo nextest run --all-features --no-fail-fast suite::sandbox::python_multiprocessing_lock_works_under_sandbox
Fri 16 Jan 2026 19:32:30 GMT
   Compiling codex-exec v0.0.0 (/home/alex/local/codex/codex-rs/exec)
    Finished `test` profile [unoptimized + debuginfo] target(s) in 1.94s
────────────
 Nextest run ID 747afdf0-91b4-47cc-b903-8acae56c410e with nextest profile: default
    Starting 1 test across 107 binaries (3199 tests skipped)
        PASS [   0.128s] codex-exec::all suite::sandbox::python_multiprocessing_lock_works_under_sandbox
────────────
     Summary [   0.138s] 1 test run: 1 passed, 3199 skipped

View original on GitHub ↗

This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗