-
Notifications
You must be signed in to change notification settings - Fork 677
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 signal_ignore()
and signal_default()
#2191
base: master
Are you sure you want to change the base?
Conversation
Provide safe mechanisms to ignore or reset a signal's action to the default. Fixes nix-rust#587.
I can see the value of this PR; it allows something to be done safely that was previously only possible unsafely. It also avoids the problem that the existing pub struct MaybeSigAction {
/// Cast into a `SigAction`.
///
/// # Safety
/// There is no guarantee that the old signal handler was installed correctly. If it was installed by this crate, it will be. But
/// if it was installed by, for example, C code, then there is no guarantee its function pointer is valid. In that case, this
/// function effectively dereferences a raw pointer of unknown provenance.
unsafe fn into(self) -> SigAction {...}
}
pub enum Signal {SIGHUP, SIGINT, ...}
impl Signal {
pub fn kill(...) {...}
pub fn killpg(...) {...}
pub fn is_default() {...}
pub fn set_default(...) {...}
pub fn set_handler(...) -> Result<MaybeSigAction> {...}
pub fn get_handler() -> Result<MaybeSigAction> {...}
...
} This API provides better namespacing than the original. With appropriately chosen definitions for types like SigAction and Handler it eliminates the unused mask and flags fields when setting the SIG_IGN or SIG_DFL. And it eliminates unsafety by moving it to a final casting step. So you can use it like this: /// Set a signal handler safely, ignoring the old value
let _ = Signal::SIGINT.set_handler(...).unwrap();
/// Set a signal handler and unsafely dereference the old handler
let old: SigAction = unsafe{ Signal::SIGINT.set_handler(...).unwrap().into() } What do you think, @SteveLauC ? |
Thanks for having a look!
To my eye this is reasonable because the upper layer is adding the "safety functionality", but I'm looking at it from a pretty narrow scope.
My goal is to make it possible to ignore signals/reset actions safely, I'm definitely not precious about the method naming or implementation. Very happy to adjust for clarity, etc.
I can see how a wider re-work could end up in a better place overall.
I believe this would need to remain unsafe because of all the regular restrictions that POSIX puts on signal handler behavior (reentrancy, minimal interactions with global state, async-signal-safe functions only, etc). |
Sorry for the late response, I think I accidentally ignored that ping. I believe we should allow our users to do the following things in safe Rust:
For the interface, I slightly tend to the functions proposed in this PR, the 4 functions may be a little more, we can probably do:
enum SafeSignalHanlder {
Default,
Ignore,
}
fn signal_is(sig: Signal, handler: SafeSignalHandler) -> Result<bool>;
fn signal_set(sig: Signal, handler: SafeSignalHandler) -> Result<()>; For the mechanism to query existing signal handler, I tend to change the pub unsafe fn sigaction(signal: Signal, sigaction: Option<&SigAction>) -> Result<SigAction>
I think @asomers' s proposal isolates all the unsafety into |
What does this PR do
Provide safe mechanisms to ignore or reset a signal's action to the default.
Fixes #587.
Checklist:
CONTRIBUTING.md