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