-
Notifications
You must be signed in to change notification settings - Fork 1.3k
signal support #1189
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 #1189
Conversation
vm/src/frame.rs
Outdated
@@ -163,6 +163,7 @@ impl Frame { | |||
/// Execute a single instruction. | |||
#[allow(clippy::cognitive_complexity)] | |||
fn execute_instruction(&self, vm: &VirtualMachine) -> FrameResult { | |||
vm.check_signals(); |
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 think this contraption makes sense, it inserts signals nicely at a defined point of time.
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.
Do you think this is a good point?
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 think so, we would have to wait for builtin functions to finish, but then again, we do not face threading issues.
vm/src/vm.rs
Outdated
// TODO: 64 | ||
pub const NSIG: usize = 10; | ||
|
||
pub static mut TRIGGERS: [AtomicBool; NSIG] = [ |
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.
Maybe you could use Default::default()
here?
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.
Did not work. I will create a procedural macro in the future to solve this duplication.
vm/src/vm.rs
Outdated
AtomicBool::new(false), | ||
AtomicBool::new(false), | ||
AtomicBool::new(false), | ||
AtomicBool::new(false), |
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.
Should this be a boolean flag, or a queue of events? Each event triggers a callback, so if we have multiple events happening in a short time, the boolean flag was already true, so it was not handled. I propose to create a queue of events per signal.
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.
This will be different from the CPython
implementation. Maybe we should leave this for as future improvement?
vm/src/vm.rs
Outdated
@@ -160,6 +179,7 @@ impl VirtualMachine { | |||
trace_func, | |||
use_tracing: RefCell::new(false), | |||
settings, | |||
signal_handlers: RefCell::new(HashMap::new()), |
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.
You could use Default::default()
here instead of RefCell::new(HashMap::new())
vm/src/vm.rs
Outdated
// TODO: 64 | ||
pub const NSIG: usize = 10; | ||
|
||
pub static mut TRIGGERS: [AtomicBool; NSIG] = [ |
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.
Having this variable as a static global would prevent multiple VirtualMachine instances. We can solve this, by moving the triggers struct into a RefCell. Place this RefCell into the signals.rs file. In the signals.rs file, create a global cell, with a trigger list. Each vm then can register a trigger list to.
Okay, my explanation is poor. Lets see how this evolves further :).
vm/src/vm.rs
Outdated
panic!("Signum bigger then NSIG"); | ||
} | ||
let triggerd; | ||
unsafe { |
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.
Please move this unsafe code into the signal module. This function should just loop over the list of triggered events. Also, you probably want to guard this for loop with some sort of lock. Another solution would be to use the std::sync::mpsc
fifo, which is thread safe. This might be handy, so that the signal handlers still can add events, while this loop still is processing.
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.
There is not problem that the an event will be added while I process the list. I will just process it in the next run.
vm/src/vm.rs
Outdated
if *signum as usize >= NSIG { | ||
panic!("Signum bigger then NSIG"); | ||
} | ||
let triggerd; |
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.
This can just be let triggerd = unsafe { ... };
let sig_ign = vm.get_attribute(signal, "SIG_DFL")?; | ||
let signalnum = signalnum.as_bigint().to_i32().unwrap(); | ||
let signal_enum = signal::Signal::from_c_int(signalnum).unwrap(); | ||
let sig_handler = if handler.is(&sig_dfl) { |
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.
@windelbouwman @coolreader18 any suggestion on how should I do this? This don't actually works...
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.
Ignore this. I had a typo...
I changed the code to use |
vm/src/frame.rs
Outdated
use crate::stdlib::signal::check_signals; | ||
|
||
#[cfg(target_arch = "wasm32")] | ||
fn check_signals(vm: &VirtualMachine) {} |
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.
Instead of defining a stub function for wasm, make the code on line 172 also depending on configuration.
vm/src/stdlib/signal.rs
Outdated
{ | ||
return Err(vm.new_type_error("Hanlder must be callable".to_string())); | ||
} | ||
let signal = vm.import("signal", &vm.ctx.new_tuple(vec![]), 0)?; |
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.
For clarity, you might consider naming this variable signal_module
.
vm/src/stdlib/signal.rs
Outdated
|
||
#[derive(Debug)] | ||
enum SigMode { | ||
Ign, |
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 this abbreviate Ignore
? We might want to use Ignore
, Default
and Handler
here instead of the abbreviations to prevent confusion.
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 removed the enum as it is not needed now that I use the same code for windows and linux.
.get(&(signum as i32)) | ||
.expect("Handler should be set") | ||
.clone(); | ||
vm.invoke(handler, vec![vm.new_int(signum), vm.get_none()]) |
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.
What should happen when a signal handler throws an exception? Do you want to tackle this now, or implement it later?
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 would prefer to do it later
This is a very initial support in signals. I wanted to get early feedback as this is harder then expected in
Rust
.This is based on the
CPython
signal handling. This article is actually explaining very nicely on how it works.