-
Notifications
You must be signed in to change notification settings - Fork 471
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
Signal support #822
Signal support #822
Conversation
Allows custom blocks to update if a specified SIGRT signal is recieved, also adds support for potential future SIGRT support for other blocks. Spawns a new thread that listens for specified signals, this uses the signal_hook crate. Expands the blocks trait to allow for a signal event as well as to be able to ask it for which potential signal a block is listening to. The get_signal() function might be unneeded and could be removed if we are willing to listen to any RTSIG signal rather than only the ones specified. Currently i3status-rs will crash if it recieves a RTSIG signal that it has not specifically asked to listen to, this was done in order to make debugging this easier.
Restructure and move functions that deal with signals into their own file. Remove the functionality that listened only to the relevant signals rather than every SIGRT event. The reasoning behind this is that it required a significant amount of general code for example an extra trait function in the blocks trait without bringing any important functionality. The original reason for selective signal listening was in order to make debugging easier when a non-listened to signal caused a crash. Now we avoid crashing instead. Right now we are listening to every SIGRT event within the allowed span (SIG 34 - 64). Of course blocks will only update if their corresponding signal is sent still.
I guess we just have to wait for this: nix-rust/nix#1143 Can you update blocks.md as well? |
I haven't had time to test it yet, how has it been going for you so far? |
I have used this feature on my own computer, it works fine. I updated the relevant blocks.md parts. So far I don't know how to get the relevant constants in a dynamic way (perhaps we could add C-bindings). The options that I see available are:
I'll let the community (or you) decide with what direction they want to go, I do not mind helping with the decided way assuming it's not too much work. |
I'll add on to that list of possible solutions. |
On mobile now so can't review the code but what happens in the case a user sets an invalid signal value? (In the case that we don't check the bounds ourselves and someone sets something like 99) |
//In ConfigBlock::new()...
if let Some(signal) = block_config.signal {
// If the signal is not in the valid range we return an error
if signal < 0 || signal > SIGMAX - SIGMIN {
return Err(Error::BlockError(
custom.id,
format!("The provided signal was out of bounds. An allowed signal needs to be between {} and {}", 0, SIGMAX - SIGMIN)
));
} else {
custom.signal = Some(signal + SIGMIN)
}
};
} It returns an error from the ConfigBlock::new() method. |
Sorry I meant something like this: For example say we hardcoded the range as 34 to 64, what would happen in the two situations below.
https://man7.org/linux/man-pages/man7/signal.7.html
Or realistically, if SIGRTMIN and SIGRTMAX only vary on non-Linux kernels then we could hardcode the range without any any worries? |
Well this would cause incorrect behavior but not necessarily break anything. If their SIGRTMIN is 35 and they choose to listen to signal 0 (which corresponds to 34) then the result would be that for them to update i3status-rs they'd have to send SIGRTMIN-1 which would be an occupied signal.
As far as I know SIGRTMAX does not vary, someone having 20 realtime signals would have to be a result of SIGRTMIN being 44 which would be the same problem as the previous one.
Well, if we are only targeting Linux kernels and SIGRTMIN and SIGRTMAX do not vary on Linux kernels then no issue would appear. I have not seen a guarantee that they do not vary however. In fact in the man-page you referenced it seems to indicate that it can sometimes be 35 on Linux kernels. It seems that libc is open to adding SIGRTMIN support to their library, I'm thinking I might try to add it myself when I get around to it. This means that eventually we should be able to add this feature correctly regardless of merging it right now, but if we do merge it right now we can always push a fix later. |
Yeah that was what I was trying to hint at.
I guess we could just make our range start a bit higher like 40 - 64 to be safe, at least until libc is enhanced. |
So, I just checked how difficult it is to bring the SIGRTMIN into rust through C bindings, super simple. I didn't realize this before so I learned my lesson. I'll try to update this right now. How does that sound? |
Sounds reasonable to me. Hopefully nix/libc get updated by the next time we want to do a release. Do you think we could also add support for a signal that schedules an update for the whole bar (every block) at once? Maybe could use SIGUSR1 or SIGUSR2 for that. In addition to the above another use case we could hopefully cover at some time is reloading the config (see #302) but this one probably isn't trivial enough to cover with this PR. |
Remove the hardcoded values for SIGRTMIN and SIGRTMAX and replace them with C bindings. This fixes the bug that could potentially occur if the kernel does not have SIGRTMIN = 34 and SIGRTMAX = 64. The C bindings should be replaced with libc or nix crate bindings when these become avaliable.
I added the C-bindings, there shouldn't be an issue now. I could also look a bit at the reloading thing. But again better left to another PR. :) |
SIGUSR1 now refreshes each block, SIGUSR2 is listened for but nothing is currently done when the signal is recieved, this feature should be saved for refreshing the .toml config file.
LGTM! I suppose in the future the implementation could be made block agnostic so it can apply to any block, but it's not a cause for delaying this PR. Thanks for working on this! |
Fantastic! Currently no documentation exists that SIGUSR1 updates all blocks, I don't know where this fits. Not sure if it is necessary but just giving a heads up. Thanks for letting me work on this! 💯 |
Good catch. Not really sure where to put it either. I think the README needs a rewrite. |
Add a status field to the custom block that takes a value between 0 and 30. These correspond to SIGRTMIN+0 to SIGRTMIN+30.
This causes the block to be updated by sending the corresponding SIGRT signal to i3status-rs. This can be done via
pkill -SIGRTMIN+1 i3status-rs
in order to send a signal to blocks listening for signal 1.This feature allows custom blocks to not need to be updated on an interval, but instead can be updated via scripts sending a signal when they need to update.
A possible flaw is that I was not able to find a good way of pulling in the signal range dynamically from the users computer, instead the range is hard-coded to listen to signals between 34 and 64 (where this is the range on my computer).
The relevant constants can be found in src/signals.rs