wip
This commit is contained in:
parent
354fc28e5d
commit
b206b55c17
|
@ -11,9 +11,9 @@ use nu_plugin_protocol::{
|
||||||
PluginOutput, ProtocolInfo,
|
PluginOutput, ProtocolInfo,
|
||||||
};
|
};
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
engine::{ctrlc, Closure, Sequence},
|
engine::{Closure, Sequence},
|
||||||
Config, DeclId, LabeledError, PipelineData, PluginMetadata, PluginSignature, ShellError,
|
Config, DeclId, Handler, HandlerGuard, Handlers, LabeledError, PipelineData, PluginMetadata,
|
||||||
Signals, Span, Spanned, Value,
|
PluginSignature, ShellError, SignalAction, Signals, Span, Spanned, Value,
|
||||||
};
|
};
|
||||||
use nu_utils::SharedCow;
|
use nu_utils::SharedCow;
|
||||||
use std::{
|
use std::{
|
||||||
|
@ -66,8 +66,8 @@ struct EngineInterfaceState {
|
||||||
writer: Box<dyn PluginWrite<PluginOutput>>,
|
writer: Box<dyn PluginWrite<PluginOutput>>,
|
||||||
// Mirror signals from `EngineState`
|
// Mirror signals from `EngineState`
|
||||||
signals: Signals,
|
signals: Signals,
|
||||||
/// Registered Ctrl-C handlers
|
/// Registered signal handlers
|
||||||
ctrlc_handlers: ctrlc::Handlers,
|
signal_handlers: Handlers,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for EngineInterfaceState {
|
impl std::fmt::Debug for EngineInterfaceState {
|
||||||
|
@ -122,7 +122,7 @@ impl EngineInterfaceManager {
|
||||||
engine_call_subscription_sender: subscription_tx,
|
engine_call_subscription_sender: subscription_tx,
|
||||||
writer: Box::new(writer),
|
writer: Box::new(writer),
|
||||||
signals: Signals::new(Arc::new(AtomicBool::new(false))),
|
signals: Signals::new(Arc::new(AtomicBool::new(false))),
|
||||||
ctrlc_handlers: ctrlc::Handlers::new(),
|
signal_handlers: Handlers::new(),
|
||||||
}),
|
}),
|
||||||
protocol_info_mut,
|
protocol_info_mut,
|
||||||
plugin_call_sender: Some(plug_tx),
|
plugin_call_sender: Some(plug_tx),
|
||||||
|
@ -337,9 +337,12 @@ impl InterfaceManager for EngineInterfaceManager {
|
||||||
});
|
});
|
||||||
self.send_engine_call_response(id, response)
|
self.send_engine_call_response(id, response)
|
||||||
}
|
}
|
||||||
PluginInput::Ctrlc => {
|
PluginInput::Signal(action) => {
|
||||||
self.state.signals.trigger();
|
match action {
|
||||||
self.state.ctrlc_handlers.run();
|
SignalAction::Interrupt => self.state.signals.trigger(),
|
||||||
|
SignalAction::Reset => self.state.signals.reset(),
|
||||||
|
}
|
||||||
|
self.state.signal_handlers.run(action);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -523,11 +526,8 @@ impl EngineInterface {
|
||||||
|
|
||||||
/// Register a closure which will be called when the engine receives a Ctrl-C signal. Returns a
|
/// Register a closure which will be called when the engine receives a Ctrl-C signal. Returns a
|
||||||
/// RAII guard that will keep the closure alive until it is dropped.
|
/// RAII guard that will keep the closure alive until it is dropped.
|
||||||
pub fn register_ctrlc_handler(
|
pub fn register_signal_handler(&self, handler: Handler) -> Result<HandlerGuard, ShellError> {
|
||||||
&self,
|
self.state.signal_handlers.register(handler)
|
||||||
handler: ctrlc::Handler,
|
|
||||||
) -> Result<ctrlc::Guard, ShellError> {
|
|
||||||
self.state.ctrlc_handlers.register(handler)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the full shell configuration from the engine. As this is quite a large object, it is
|
/// Get the full shell configuration from the engine. As this is quite a large object, it is
|
||||||
|
|
|
@ -99,14 +99,14 @@ mod tests {
|
||||||
let called1_clone = Arc::clone(&called1);
|
let called1_clone = Arc::clone(&called1);
|
||||||
let called2_clone = Arc::clone(&called2);
|
let called2_clone = Arc::clone(&called2);
|
||||||
|
|
||||||
let _guard1 = handlers.register(Box::new(move || {
|
let _guard1 = handlers.register(Box::new(move |_| {
|
||||||
called1_clone.store(true, Ordering::SeqCst);
|
called1_clone.store(true, Ordering::SeqCst);
|
||||||
}));
|
}));
|
||||||
let _guard2 = handlers.register(Box::new(move || {
|
let _guard2 = handlers.register(Box::new(move |_| {
|
||||||
called2_clone.store(true, Ordering::SeqCst);
|
called2_clone.store(true, Ordering::SeqCst);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
handlers.run();
|
handlers.run(SignalAction::Interrupt);
|
||||||
|
|
||||||
assert!(called1.load(Ordering::SeqCst));
|
assert!(called1.load(Ordering::SeqCst));
|
||||||
assert!(called2.load(Ordering::SeqCst));
|
assert!(called2.load(Ordering::SeqCst));
|
||||||
|
@ -119,7 +119,7 @@ mod tests {
|
||||||
let called = Arc::new(AtomicBool::new(false));
|
let called = Arc::new(AtomicBool::new(false));
|
||||||
let called_clone = Arc::clone(&called);
|
let called_clone = Arc::clone(&called);
|
||||||
|
|
||||||
let guard = handlers.register(Box::new(move || {
|
let guard = handlers.register(Box::new(move |_| {
|
||||||
called_clone.store(true, Ordering::Relaxed);
|
called_clone.store(true, Ordering::Relaxed);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ mod tests {
|
||||||
// Ensure the handler is removed after dropping the guard
|
// Ensure the handler is removed after dropping the guard
|
||||||
assert_eq!(handlers.handlers.lock().unwrap().len(), 0);
|
assert_eq!(handlers.handlers.lock().unwrap().len(), 0);
|
||||||
|
|
||||||
handlers.run();
|
handlers.run(SignalAction::Interrupt);
|
||||||
|
|
||||||
// Ensure the handler is not called after being dropped
|
// Ensure the handler is not called after being dropped
|
||||||
assert!(!called.load(Ordering::Relaxed));
|
assert!(!called.load(Ordering::Relaxed));
|
||||||
|
|
|
@ -77,15 +77,15 @@ impl Signals {
|
||||||
self.signals.is_none()
|
self.signals.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
if let Some(signals) = &self.signals {
|
if let Some(signals) = &self.signals {
|
||||||
signals.store(false, Ordering::Relaxed);
|
signals.store(false, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The types of things that can be signaled. Its anticipated this will change as we learn how we'd
|
/// The types of things that can be signaled. It's anticipated this will change as we learn more
|
||||||
/// like signals to be handled.
|
/// about how we'd like signals to be handled.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub enum SignalAction {
|
pub enum SignalAction {
|
||||||
Interrupt,
|
Interrupt,
|
||||||
|
|
|
@ -16,7 +16,7 @@ impl PluginCommand for Ctrlc {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Example command that demonstrates registering a ctrl-c handler"
|
"Example command that demonstrates registering an interrupt signal handler"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
|
@ -35,12 +35,12 @@ impl PluginCommand for Ctrlc {
|
||||||
_input: PipelineData,
|
_input: PipelineData,
|
||||||
) -> Result<PipelineData, LabeledError> {
|
) -> Result<PipelineData, LabeledError> {
|
||||||
let (sender, receiver) = mpsc::channel::<()>();
|
let (sender, receiver) = mpsc::channel::<()>();
|
||||||
let _guard = engine.register_ctrlc_handler(Box::new(move || {
|
let _guard = engine.register_signal_handler(Box::new(move |_| {
|
||||||
let _ = sender.send(());
|
let _ = sender.send(());
|
||||||
}));
|
}));
|
||||||
|
|
||||||
eprintln!("interrupt status: {:?}", engine.signals().interrupted());
|
eprintln!("interrupt status: {:?}", engine.signals().interrupted());
|
||||||
eprintln!("waiting for ctrl-c signal...");
|
eprintln!("waiting for interrupt signal...");
|
||||||
receiver.recv().expect("handler went away");
|
receiver.recv().expect("handler went away");
|
||||||
eprintln!("interrupt status: {:?}", engine.signals().interrupted());
|
eprintln!("interrupt status: {:?}", engine.signals().interrupted());
|
||||||
eprintln!("peace.");
|
eprintln!("peace.");
|
||||||
|
|
Loading…
Reference in New Issue
Block a user