This commit is contained in:
Andy Gayton 2024-07-04 21:09:34 -04:00
parent 1060b65e14
commit c781506ad2
3 changed files with 30 additions and 28 deletions

View File

@ -303,18 +303,31 @@ impl RegisteredPlugin for PersistentPlugin {
self self
} }
fn set_ctrlc_handler_guard(&self, guard: ctrlc::Guard) { fn configure_ctrlc_handler(
self: Arc<Self>,
handlers: &ctrlc::Handlers,
) -> Result<(), ShellError> {
let guard = {
// We take a weakref to the plugin so that we don't create a cycle to the
// RAII guard that will be stored on the plugin.
let plugin = Arc::downgrade(&self);
handlers.register(Box::new(move || {
// If the plugin is still alive, call its ctrlc handler. It should
// never be None because the guard is dropped when the plugin is.
if let Some(plugin) = plugin.upgrade() {
if let Ok(mutable) = plugin.mutable.lock() {
if let Some(ref running) = mutable.running {
let _ = running.interface.ctrlc();
}
}
}
}))?
};
if let Ok(mut mutable) = self.mutable.lock() { if let Ok(mut mutable) = self.mutable.lock() {
mutable.ctrlc_guard = Some(guard); mutable.ctrlc_guard = Some(guard);
} }
}
fn ctrlc(&self) -> Result<(), ShellError> {
if let Ok(mutable) = self.mutable.lock() {
if let Some(ref running) = mutable.running {
return running.interface.ctrlc();
}
}
Ok(()) Ok(())
} }
} }

View File

@ -258,24 +258,13 @@ impl EngineState {
#[cfg(feature = "plugin")] #[cfg(feature = "plugin")]
if !delta.plugins.is_empty() { if !delta.plugins.is_empty() {
// Replace plugins that overlap in identity.
for plugin in std::mem::take(&mut delta.plugins) { for plugin in std::mem::take(&mut delta.plugins) {
if let Some(handlers) = self.ctrlc_handlers.as_ref() { // Connect plugins to the ctrlc handlers
let guard = { if let Some(handlers) = &self.ctrlc_handlers {
// We take a weakref to the plugin so that we don't create a cycle to the plugin.clone().configure_ctrlc_handler(handlers)?;
// RAII guard that will be stored on the plugin.
let plugin = Arc::downgrade(&plugin);
handlers.register(Box::new(move || {
// If the plugin is still alive, call its ctrlc handler. It should
// never be None because the guard is dropped when the plugin is.
if let Some(plugin) = plugin.upgrade() {
let _ = plugin.ctrlc();
}
}))?
};
plugin.set_ctrlc_handler_guard(guard);
} }
// Replace plugins that overlap in identity.
if let Some(existing) = self if let Some(existing) = self
.plugins .plugins
.iter_mut() .iter_mut()

View File

@ -35,11 +35,11 @@ pub trait RegisteredPlugin: Send + Sync {
/// plugins. /// plugins.
fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>; fn as_any(self: Arc<Self>) -> Arc<dyn Any + Send + Sync>;
/// Set a reference to the RAII guard for the plugin's Ctrl-C handler. /// Give this plugin a chance to register for Ctrl-C signals.
fn set_ctrlc_handler_guard(&self, _guard: ctrlc::Guard) {} fn configure_ctrlc_handler(
self: Arc<Self>,
/// Send a Ctrl-C signal to the plugin. _handler: &ctrlc::Handlers,
fn ctrlc(&self) -> Result<(), ShellError> { ) -> Result<(), ShellError> {
Ok(()) Ok(())
} }
} }