Conversation
vm/src/frame.rs
Outdated
| /// 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.
I think this contraption makes sense, it inserts signals nicely at a defined point of time.
There was a problem hiding this comment.
Do you think this is a good point?
There was a problem hiding this comment.
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.
Maybe you could use Default::default() here?
There was a problem hiding this comment.
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.
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.
This will be different from the CPython implementation. Maybe we should leave this for as future improvement?
vm/src/vm.rs
Outdated
| trace_func, | ||
| use_tracing: RefCell::new(false), | ||
| settings, | ||
| signal_handlers: RefCell::new(HashMap::new()), |
There was a problem hiding this comment.
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.
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.
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.
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.
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.
@windelbouwman @coolreader18 any suggestion on how should I do this? This don't actually works...
There was a problem hiding this comment.
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.
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.
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.
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.
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.
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.
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
CPythonsignal handling. This article is actually explaining very nicely on how it works.