-
Notifications
You must be signed in to change notification settings - Fork 783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add sync::OnceExt
and sync::OnceLockExt
traits
#4676
Conversation
That's OK. Single-initialization comes up a lot so we should take our time and get it right. I also want to add a section to the guide about how to use threads from both Python and rust and how free-threading changes things. I may expand the existing parallelism docs if needed. Having some time to do that is nice! |
// Some other thread filled this Once, so we need to restore the GIL state. | ||
unsafe { ffi::PyEval_RestoreThread(ts) }; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wrote a test for this trait based on the standard library example for try_once_force
and it crashed Python because the thread state was corrupted. I think this code won't restore the thread state correctly if a panic happens inside f()
and the fix is to use the RAII guard pattern. Assuming that's right, I'll go ahead and push a fix along with the test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does the guard fix your problem? That'd be surprising to me, because I reviewed the previous implementation and believed it was sound.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh nevermind; I read the Once documentation and if it is poisoned it will panic before the closure is called.
I looked at including |
We do? https://github.com/PyO3/pyo3/blob/main/pyo3-build-config/src/lib.rs#L138 |
Sorry, missed that! Thanks for the link. |
sync::OnceExt
traitsync::OnceExt
and sync::OnceLockExt
traits
I think I did it right, but clippy complains that I'm using features that aren't in the MSRV. OK to ignore that or did I mess something up? |
}); | ||
}); | ||
assert_eq!(cell.get(), Some(&12345)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestions welcome for a more interesting test
}); | ||
# } | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I probably want to rewrite this example to use OnceLock
That's annoying. You can set it to allow here: https://github.com/PyO3/pyo3/blob/main/Cargo.toml#L153 |
I just locally ignored it, I still think that clippy lint is useful and it doesn't look like we use features that aren't in the MSRV very often. |
Thanks, this looks great to me! I simplified the |
The new tests that use threads need to be skipped on emscripten. |
Related to #4513, #4671
It turns out that within our test suite the racy behaviour of
GILOnceCell
is already problematic on GIL-enabled builds, and is just waiting for additional GIL switches to bait out problems 😬. In particular intest_declarative_module
we have a race which might attempt to create a module twice; we explicitly forbid this because we don't support subinterpreters.This PR introduces
pyo3::sync::OnceExt
, which adds helper methods tostd::sync::Once
which avoid deadlocking with the GIL by releasing if necessary before blocking.This solves the issue with
test_declarative_module
by using theOnce
to guarantee we only ever create the module once.I think we should document this in the FAQ and freethreading guides, and probably this is good justification for getting #4513 and maybe also some
OnceCellExt
traits into 0.23. cc @ngoldbaum, I guess this would delay the release by a few days.