Skip to content

Conversation

@ngoldbaum
Copy link
Contributor

@ngoldbaum ngoldbaum commented Nov 21, 2025

Python 3.14 introduced new variants for the critical section macros that accept a PyMutex instead of a PyObject. See python/cpython#133296, capi-workgroup/decisions#67, and python/cpython#135899 for more details.

I also was responsible for making sure this landed in 3.14, so shipping this PR is special to me as it completes the loop :)

So far I don't think there are any open source uses yet because it's so new and it's 3.14-specific.

The new APIs accept an EnteredCriticalSection which exposes unsafe get and get_mut methods because the caller needs to guarantee that the closure doesn't unsafely release the resource protected by the PyMutex.

I also expanded the docs for the existing critical section API wrappers to clarify things a bit.

@ngoldbaum ngoldbaum marked this pull request as draft November 21, 2025 20:55
@ngoldbaum

This comment was marked as resolved.

@ngoldbaum ngoldbaum force-pushed the critical-section-mutex-2 branch from 5830242 to 0621775 Compare November 24, 2025 19:50
/// while the closure `f` is executing. The critical section may be temporarily
/// released and re-acquired if the closure calls back into the interpreter in
/// a manner that would block. This is similar to how the GIL can be released
/// during blocking calls. See the safety notes below for caveats about

This comment was marked as outdated.

@ngoldbaum ngoldbaum marked this pull request as ready for review November 24, 2025 20:43
@ngoldbaum
Copy link
Contributor Author

I marked this ready for review but I expect it to have at least one more round. I left a couple questions for others and comments for myself inline.

src/sync.rs Outdated
#[cfg_attr(not(Py_GIL_DISABLED), allow(unused_variables))]
pub fn with_critical_section_mutex<'py, F, R, T>(_py: Python<'py>, mutex: &PyMutex<T>, f: F) -> R
where
F: FnOnce(&UnsafeCell<T>) -> R,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way to make the "safety" of this clearer would be to package the UnsafeCell up as something like

struct EnteredCriticalSection<'a, T>(&'a UnsafeCell<T>);

impl<T> EnteredCriticalSection<'_, T> {
    unsafe fn get(&mut self) -> &mut T { ... }
}

Can then document safety invariants on the get function. It's also a bit nicer than users having to go through UnsafeCell::get themselves (and a raw pointer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, see latest changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants