Skip to content

Commit 04b7c4a

Browse files
committed
Merge remote-tracking branch 'upstream/main' into bytecode-enum-named-data
2 parents a828ab1 + 7eb1821 commit 04b7c4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+435
-343
lines changed

.github/workflows/upgrade-pylib.lock.yml

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_posix.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -668,6 +668,19 @@ def test_fstat(self):
668668
finally:
669669
fp.close()
670670

671+
@unittest.expectedFailure # TODO: RUSTPYTHON
672+
@unittest.skipUnless(hasattr(posix, 'stat'),
673+
'test needs posix.stat()')
674+
@unittest.skipUnless(os.stat in os.supports_follow_symlinks,
675+
'test needs follow_symlinks support in os.stat()')
676+
def test_stat_fd_zero_follow_symlinks(self):
677+
with self.assertRaisesRegex(ValueError,
678+
'cannot use fd and follow_symlinks together'):
679+
posix.stat(0, follow_symlinks=False)
680+
with self.assertRaisesRegex(ValueError,
681+
'cannot use fd and follow_symlinks together'):
682+
posix.stat(1, follow_symlinks=False)
683+
671684
def test_stat(self):
672685
self.assertTrue(posix.stat(os_helper.TESTFN))
673686
self.assertTrue(posix.stat(os.fsencode(os_helper.TESTFN)))
@@ -1017,7 +1030,6 @@ def test_chmod_dir(self):
10171030
target = self.tempdir()
10181031
self.check_chmod(posix.chmod, target)
10191032

1020-
@unittest.skipIf(sys.platform in ("darwin", "linux"), "TODO: RUSTPYTHON; crash")
10211033
@os_helper.skip_unless_working_chmod
10221034
def test_fchmod_file(self):
10231035
with open(os_helper.TESTFN, 'wb+') as f:

benches/microbenchmarks.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ fn bench_rustpython_code(group: &mut BenchmarkGroup<WallTime>, bench: &MicroBenc
134134
if let Some(idx) = iterations {
135135
scope
136136
.locals
137+
.as_ref()
138+
.expect("new_scope_with_builtins always provides locals")
137139
.as_object()
138140
.set_item("ITERATIONS", vm.new_pyobj(idx), vm)
139141
.expect("Error adding ITERATIONS local variable");

crates/common/src/lock.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,42 @@ pub type PyRwLockWriteGuard<'a, T> = RwLockWriteGuard<'a, RawRwLock, T>;
5757
pub type PyMappedRwLockWriteGuard<'a, T> = MappedRwLockWriteGuard<'a, RawRwLock, T>;
5858

5959
// can add fn const_{mutex,rw_lock}() if necessary, but we probably won't need to
60+
61+
/// Reset a `PyMutex` to its initial (unlocked) state after `fork()`.
62+
///
63+
/// After `fork()`, locks held by dead parent threads would deadlock in the
64+
/// child. This writes `RawMutex::INIT` via the `Mutex::raw()` accessor,
65+
/// bypassing the normal unlock path which may interact with parking_lot's
66+
/// internal waiter queues.
67+
///
68+
/// # Safety
69+
///
70+
/// Must only be called from the single-threaded child process immediately
71+
/// after `fork()`, before any other thread is created.
72+
#[cfg(unix)]
73+
pub unsafe fn reinit_mutex_after_fork<T: ?Sized>(mutex: &PyMutex<T>) {
74+
// Use Mutex::raw() to access the underlying lock without layout assumptions.
75+
// parking_lot::RawMutex (AtomicU8) and RawCellMutex (Cell<bool>) both
76+
// represent the unlocked state as all-zero bytes.
77+
unsafe {
78+
let raw = mutex.raw() as *const RawMutex as *mut u8;
79+
core::ptr::write_bytes(raw, 0, core::mem::size_of::<RawMutex>());
80+
}
81+
}
82+
83+
/// Reset a `PyRwLock` to its initial (unlocked) state after `fork()`.
84+
///
85+
/// Same rationale as [`reinit_mutex_after_fork`] — dead threads' read or
86+
/// write locks would cause permanent deadlock in the child.
87+
///
88+
/// # Safety
89+
///
90+
/// Must only be called from the single-threaded child process immediately
91+
/// after `fork()`, before any other thread is created.
92+
#[cfg(unix)]
93+
pub unsafe fn reinit_rwlock_after_fork<T: ?Sized>(rwlock: &PyRwLock<T>) {
94+
unsafe {
95+
let raw = rwlock.raw() as *const RawRwLock as *mut u8;
96+
core::ptr::write_bytes(raw, 0, core::mem::size_of::<RawRwLock>());
97+
}
98+
}

crates/derive-impl/src/pyclass.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ pub(crate) fn impl_pyclass_impl(attr: PunctuatedNestedMeta, item: Item) -> Resul
181181
},
182182
parse_quote! {
183183
fn __extend_py_class(
184-
ctx: &::rustpython_vm::Context,
184+
ctx: &'static ::rustpython_vm::Context,
185185
class: &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType>,
186186
) {
187187
#getset_impl
@@ -222,7 +222,7 @@ pub(crate) fn impl_pyclass_impl(attr: PunctuatedNestedMeta, item: Item) -> Resul
222222
const TP_FLAGS: ::rustpython_vm::types::PyTypeFlags = #flags;
223223

224224
fn impl_extend_class(
225-
ctx: &::rustpython_vm::Context,
225+
ctx: &'static ::rustpython_vm::Context,
226226
class: &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType>,
227227
) {
228228
#impl_ty::__extend_py_class(ctx, class);
@@ -284,7 +284,7 @@ pub(crate) fn impl_pyclass_impl(attr: PunctuatedNestedMeta, item: Item) -> Resul
284284
},
285285
parse_quote! {
286286
fn __extend_py_class(
287-
ctx: &::rustpython_vm::Context,
287+
ctx: &'static ::rustpython_vm::Context,
288288
class: &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType>,
289289
) {
290290
#getset_impl

crates/vm/src/builtins/asyncgenerator.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ impl Drop for PyAsyncGen {
810810
}
811811
}
812812

813-
pub fn init(ctx: &Context) {
813+
pub fn init(ctx: &'static Context) {
814814
PyAsyncGen::extend_class(ctx, ctx.types.async_generator);
815815
PyAsyncGenASend::extend_class(ctx, ctx.types.async_generator_asend);
816816
PyAsyncGenAThrow::extend_class(ctx, ctx.types.async_generator_athrow);

crates/vm/src/builtins/bool.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ impl Representable for PyBool {
182182
}
183183
}
184184

185-
pub(crate) fn init(context: &Context) {
185+
pub(crate) fn init(context: &'static Context) {
186186
PyBool::extend_class(context, context.types.bool_type);
187187
}
188188

crates/vm/src/builtins/builtin_func.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ impl fmt::Debug for PyNativeMethod {
224224
}
225225
}
226226

227-
pub fn init(context: &Context) {
227+
pub fn init(context: &'static Context) {
228228
PyNativeFunction::extend_class(context, context.types.builtin_function_or_method_type);
229229
}
230230

crates/vm/src/builtins/bytearray.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl PyPayload for PyByteArray {
6767
}
6868

6969
/// Fill bytearray class methods dictionary.
70-
pub(crate) fn init(context: &Context) {
70+
pub(crate) fn init(context: &'static Context) {
7171
PyByteArray::extend_class(context, context.types.bytearray_type);
7272
PyByteArrayIterator::extend_class(context, context.types.bytearray_iterator_type);
7373
}

crates/vm/src/builtins/bytes.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ impl PyPayload for PyBytes {
8686
}
8787
}
8888

89-
pub(crate) fn init(context: &Context) {
89+
pub(crate) fn init(context: &'static Context) {
9090
PyBytes::extend_class(context, context.types.bytes_type);
9191
PyBytesIterator::extend_class(context, context.types.bytes_iterator_type);
9292
}

0 commit comments

Comments
 (0)