Skip to content

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

Merged
merged 27 commits into from
Aug 4, 2019
Merged

signal support #1189

merged 27 commits into from
Aug 4, 2019

Conversation

palaviv
Copy link
Contributor

@palaviv palaviv commented Jul 28, 2019

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.

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();
Copy link
Contributor

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.

Copy link
Contributor Author

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?

Copy link
Contributor

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] = [
Copy link
Contributor

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?

Copy link
Contributor Author

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),
Copy link
Contributor

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.

Copy link
Contributor Author

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()),
Copy link
Contributor

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] = [
Copy link
Contributor

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 {
Copy link
Contributor

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.

Copy link
Contributor Author

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;
Copy link
Member

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) {
Copy link
Contributor Author

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...

Copy link
Contributor Author

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...

@palaviv palaviv marked this pull request as ready for review August 2, 2019 06:44
@palaviv palaviv changed the title [WIP] signal support signal support - UNIX Aug 2, 2019
@palaviv palaviv changed the title signal support - UNIX signal support Aug 3, 2019
@palaviv
Copy link
Contributor Author

palaviv commented Aug 3, 2019

I changed the code to use libc directly so it will work on Windows. I will test the code on Windows after adding os.kill.

vm/src/frame.rs Outdated
use crate::stdlib::signal::check_signals;

#[cfg(target_arch = "wasm32")]
fn check_signals(vm: &VirtualMachine) {}
Copy link
Contributor

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.

{
return Err(vm.new_type_error("Hanlder must be callable".to_string()));
}
let signal = vm.import("signal", &vm.ctx.new_tuple(vec![]), 0)?;
Copy link
Contributor

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.


#[derive(Debug)]
enum SigMode {
Ign,
Copy link
Contributor

@windelbouwman windelbouwman Aug 3, 2019

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.

Copy link
Contributor Author

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()])
Copy link
Contributor

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?

Copy link
Contributor Author

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

@windelbouwman windelbouwman merged commit 2613ee4 into RustPython:master Aug 4, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants