This commit is contained in:
Andy Gayton 2024-08-01 12:47:51 -04:00
parent 354fc28e5d
commit b206b55c17
4 changed files with 25 additions and 25 deletions

View File

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

View File

@ -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));

View File

@ -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,

View File

@ -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.");