* Suspend Python threads before fork()
Add stop-the-world thread suspension around fork() to prevent
deadlocks from locks held by dead parent threads in the child.
- Thread states: DETACHED / ATTACHED / SUSPENDED with atomic CAS
transitions matching _PyThreadState_{Attach,Detach,Suspend}
- stop_the_world / start_the_world: park all non-requester threads
before fork, resume after (parent) or reset (child)
- allow_threads (Py_BEGIN/END_ALLOW_THREADS): detach around blocking
syscalls (os.read/write, waitpid, Lock.acquire, time.sleep) so
stop_the_world can force-park via CAS
- Acquire/release import lock around fork lifecycle
- zero_reinit_after_fork: generic lock reset for parking_lot types
- gc_clear_raw: detach dict instead of clearing entries
- Lock-free double-check for descriptor cache reads (no read-side
seqlock); write-side seqlock retained for writer serialization
- fork() returns PyResult, checks PythonFinalizationError, calls
sys.audit
* Object header slimming: prefix allocation for ObjExt
Extract dict, weak_list, and slots fields from PyInner<T> into a
separate ObjExt struct allocated as a prefix before PyInner using
Layout::extend(). Objects that don't need these fields (int, str,
float, list, tuple, dict, etc.) skip the prefix entirely.
- Add HAS_WEAKREF flag to PyTypeFlags for per-type weakref control
- Add HAS_EXT bit to GcBits indicating prefix presence
- Define ObjExt struct with dict, weak_list, slots
- Shrink PyInner header from ~80-88 bytes to ~32 bytes for lightweight objects
- Update all accessor methods to go through ext_ref()
- Update bootstrap type hierarchy to use prefix allocation
- Add __weakref__ getset descriptor for heap types
- Set HAS_WEAKREF on builtin types that support weak references
- Remove test_weak_keyed_bad_delitem expectedFailure (now passes)
* Add HAS_WEAKREF to _asyncio Future/Task, rename weakref helpers
- Add HAS_WEAKREF flag to PyFuture and PyTask (matches CPython)
- Rename subtype_getweakref/setweakref to subtype_get_weakref/set_weakref
to fix cspell unknown word lint
* Add HAS_WEAKREF to array, deque, _grouper; remove expectedFailure markers
- Add HAS_WEAKREF to PyArray and PyDeque (matches CPython)
- Add HAS_WEAKREF to PyItertoolsGrouper (internal use by groupby)
- Remove 6 expectedFailure markers from test_dataclasses for weakref/slots
tests that now pass
* Add HAS_WEAKREF to code, union, partial, lock, IO, mmap, sre, sqlite3, typevar types
Add HAS_WEAKREF flag to built-in types that support weakref:
- PyCode, PyUnion, PyPartial, Lock, RLock
- All IO base/concrete classes (_IOBase, _RawIOBase, _BufferedIOBase,
_TextIOBase, BufferedReader, BufferedWriter, BufferedRandom,
BufferedRWPair, TextIOWrapper, StringIO, BytesIO, FileIO,
WindowsConsoleIO)
- PyMmap, sre Pattern, sqlite3 Connection/Cursor
- TypeVar, ParamSpec, ParamSpecArgs, ParamSpecKwargs, TypeVarTuple
Remove 3 expectedFailure markers from test_descr for now-passing tests.
* Add HAS_DICT to type flags and handle non-METHOD/CLASS in descr_get
- Add HAS_DICT flag to PyType (type metaclass) alongside existing
HAS_WEAKREF. All type objects are instances of type and need dict
support, matching CPython's PyType_Type.
- Replace unimplemented!() in PyMethodDescriptor::descr_get with
fallback to bind obj directly, matching CPython's method_get which
uses PyCFunction_NewEx for non-METH_METHOD methods.
* Fix ext detection, HeapMethodDef ownership, WASM error
- Remove HAS_EXT gc_bits flag; detect ext from type flags
using raw pointer reads to avoid Stacked Borrows violations
- Store HeapMethodDef owner in payload instead of dict hack
- Clear dict entries in gc_clear_raw to break cycles
- Add WASM error fallback when exception serialization fails
* Remove unsafe ctx cast in make_class
Use Context::genesis() directly in make_class to obtain
&'static Context, eliminating the raw pointer cast.
* make_class -> make_static_type
Add non-ASCII string check to _hashlib.compare_digest, matching the
behavior of _operator._compare_digest. When both arguments are strings,
non-ASCII characters now correctly raise TypeError.
Also replace the non-constant-time == comparison with constant_time_eq
for proper timing-attack resistance, and return PyResult<bool> instead
of PyResult<PyObjectRef>.
Add #[pygetset] getter/setter for Cursor.row_factory so that Python-level
attribute access reads/writes the Rust struct field instead of the
instance dict.
Fix Connection.cursor() to only propagate the connection's row_factory
to the cursor when the connection's row_factory is not None, matching
CPython behavior. Previously it unconditionally overwrote the cursor's
row_factory, discarding any factory set by a cursor subclass __init__.
* Implement Windows SemLock in _multiprocessing module
Add SemLock class using Windows semaphore APIs (CreateSemaphoreW,
WaitForSingleObjectEx, ReleaseSemaphore) so test_multiprocessing
suites are no longer skipped with "lacks a functioning sem_open".
Also add sem_unlink as no-op and flags dict for Windows.
* Fix _multiprocessing recv to return bytes and improve SemLock reliability
- recv() now returns bytes instead of int (matching CPython)
- Remove spurious GetLastError() check after CreateSemaphoreW
- Add signal checking during blocking SemLock acquire
* Include winerror in OSError.__reduce__ on Windows
* Remove expectedFailure for tests now passing with Windows SemLock
* Fix OSError.__reduce__ to preserve winerror when filename is None
When filename is None, __reduce__ was reconstructing a 2-element
(errno, msg) tuple, dropping the winerror at position 3 in the
original args. Use the original args tuple instead, matching CPython.
* Validate maxvalue > 0 in SemLock and document winerror __reduce__ divergence
* Reject embedded null characters in mmap tagname and _winapi file mapping names
Use Win32 CreateFileMappingW + MapViewOfFile when tagname is
provided, enabling inter-process shared memory for
multiprocessing.heap.Arena. Anonymous mmaps without tagname
still use memmap2.
Remove expectedFailure from test_tagname in test_mmap.py.
- Replace ExceptionStack linked list with Vec for O(1) push/pop
- Introduce FramePtr (NonNull<Py<Frame>>) to avoid Arc clone in frame stack
- Use FramePtr in ThreadSlot for lock-protected cross-thread frame access
- Add resume_gen_frame for lightweight generator/coroutine resume
- Replace Coro.exception PyMutex with PyAtomicRef for lock-free swap
- Add with_frame_exc to support initial exception state for generators
- Use scopeguard for panic-safe cleanup in with_frame_exc/resume_gen_frame
- Add traceback entries in gen_throw delegate/close error paths
- Treat EndAsyncFor and CleanupThrow as reraise in handle_exception
- Update current_frame()/current_globals() to return owned values
- Add ThreadSlot with atomic exception field for sys._current_exceptions()
- Push/pop thread frames in resume_gen_frame for sys._current_frames()
Add _WindowsConsoleIO class to _io module with ReadConsoleW/WriteConsoleW support.
Add _testconsole stdlib module with write_input for console input simulation.
Integrate console detection in io_open to use _WindowsConsoleIO for console handles.
- Replace static_cell! cached builtins_iter/builtins_reversed with
per-call vm.builtins.get_attr lookups to support runtime builtins
mutation (CPython issue #101765)
- Refactor PositionIterInternal::reduce to take func, active, and
empty callbacks; resolve builtins outside the lock to prevent
deadlock from reentrant iterator access
- Add __reduce__ and fix reentrant next() in PyCallableIterator
- Remove expectedFailure from test_reverse_iterator_picking and
test_reduce_mutating_builtins_iter
Add `source_path: PyMutex<&'static PyStrInterned>` field to
`PyCode` for interior mutability, replacing the UB-inducing
`#[allow(invalid_reference_casting)]` + `write_volatile` pattern
in `update_code_filenames`. Update all read sites across the
codebase to use the new `source_path()` accessor method.
* Add host_env feature for sandbox isolation
Introduce a `host_env` feature flag that gates all host environment
access (filesystem, network, signals, processes). When disabled,
the VM operates in sandbox mode:
- _io module always available; FileIO gated by host_env
- SandboxStdio provides lightweight stdin/stdout/stderr via Rust std::io
- BytesIO/StringIO/BufferedIO/TextIOWrapper work without host_env
- open() returns UnsupportedOperation in sandbox
- stdlib modules (os, socket, signal, etc.) gated by host_env
- CI checks both host_env ON and OFF builds
* Auto-format: ruff check --select I --fix
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>