-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
sync::Once and panicking closure #31688
Comments
triage: I-nominated |
I don't really have an opinion on what the semantics should be in this case, but I'm curious what others think! |
I personally think the current behavior is fine (a common use case for Once it to initialize something, and if the closure panics it probably hasn't been initialized), but we should document it. |
panic inside call_once is a very broken scenario. Maybe it would only help authors of critical unsafe code if we ensured the closure could only be called once ever. The closure call could be enforced to abort on panic (it should be a "noexcept" zone).
|
Interesting, it's not broken because of FnOnce, the actual closure value is only called once (or never). |
cc me |
I prefer poisoning it, without any options to unpoison. Alternately, just leaving it alone. |
The libs team discussed this during triage yesterday and we didn't necessarily reach any concrete conclusion. As @brson mentioned we talked about how we may want to just poison a |
This commit rewrites the `std::sync::Once` primitive with poisoning in mind in light of rust-lang#31688. Currently a panic in the initialization closure will cause future initialization closures to run, but the purpose of a Once is usually to initialize some global state so it's highly likely that the global state is corrupt if a panic happened. The same strategy of a mutex is taken where a panic is propagated by default. A new API, `call_once_force`, was added to subvert panics like is available on Mutex as well (for when panicking is handled internally). Adding this support was a significant enough change to the implementation that it was just completely rewritten from scratch, primarily to avoid using a `StaticMutex` which needs to have `destroy()` called on it at some point (a pain to do). Closes rust-lang#31688
std: Rewrite Once with poisoning This commit rewrites the `std::sync::Once` primitive with poisoning in mind in light of rust-lang#31688. Currently a panic in the initialization closure will cause future initialization closures to run, but the purpose of a Once is usually to initialize some global state so it's highly likely that the global state is corrupt if a panic happened. The same strategy of a mutex is taken where a panic is propagated by default. A new API, `call_once_force`, was added to subvert panics like is available on Mutex as well (for when panicking is handled internally). Adding this support was a significant enough change to the implementation that it was just completely rewritten from scratch, primarily to avoid using a `StaticMutex` which needs to have `destroy()` called on it at some point (a pain to do). Closes rust-lang#31688
This commit rewrites the `std::sync::Once` primitive with poisoning in mind in light of rust-lang#31688. Currently a panic in the initialization closure will cause future initialization closures to run, but the purpose of a Once is usually to initialize some global state so it's highly likely that the global state is corrupt if a panic happened. The same strategy of a mutex is taken where a panic is propagated by default. A new API, `call_once_force`, was added to subvert panics like is available on Mutex as well (for when panicking is handled internally). Adding this support was a significant enough change to the implementation that it was just completely rewritten from scratch, primarily to avoid using a `StaticMutex` which needs to have `destroy()` called on it at some point (a pain to do). Closes rust-lang#31688
std: Rewrite Once with poisoning This commit rewrites the `std::sync::Once` primitive with poisoning in mind in light of #31688. Currently a panic in the initialization closure will cause future initialization closures to run, but the purpose of a Once is usually to initialize some global state so it's highly likely that the global state is corrupt if a panic happened. The same strategy of a mutex is taken where a panic is propagated by default. A new API, `call_once_force`, was added to subvert panics like is available on Mutex as well (for when panicking is handled internally). Adding this support was a significant enough change to the implementation that it was just completely rewritten from scratch, primarily to avoid using a `StaticMutex` which needs to have `destroy()` called on it at some point (a pain to do). Closes #31688
This is marked as the tracking issue for the |
Ah it's probably best to open a new tracking issue, would you be interested in doing so @durka? |
The tracking issue for once_poison was noted as rust-lang#31688 which was closed, so it now points to the new rust-lang#33577.
update tracking issue for once_poison The tracking issue for once_poison was noted as rust-lang#31688 which was closed, so it now points to the new rust-lang#33577.
The documentation for sync::Once does not clarify what happens if given closure
panics. Currently I would rather expect that call_once will execute the closure
only once, whether it panics or not. But this is not what happens:
Prints:
Either way documentation needs a slight improvement. And additionally code if
it is not a desired behaviour. As a side comment I will note that this
behaviour differs between languages. In C++ for example std::call_once to
proceed must not exit via exception, in Go on the other hand exiting via panic
counts as successful execution.
The text was updated successfully, but these errors were encountered: