store ctrlc_handlers on PersistentPlugin

This commit is contained in:
Andy Gayton 2024-07-04 16:39:50 -04:00
parent d055b9f17f
commit f6afe70947
5 changed files with 46 additions and 33 deletions

View File

@ -109,13 +109,15 @@ apparent the next time `nu` is next launched with that plugin registry file.
let custom_path = call.get_flag(engine_state, stack, "plugin-config")?; let custom_path = call.get_flag(engine_state, stack, "plugin-config")?;
// Start the plugin manually, to get the freshest signatures and to not affect engine // Start the plugin manually, to get the freshest signatures and to not affect engine
// state. Provide a GC config that will stop it ASAP // state. Provide a GC config that will stop it ASAP. We don't pass ctrlc_handlers since
// this instance is temporary and won't be used to run commands.
let plugin = Arc::new(PersistentPlugin::new( let plugin = Arc::new(PersistentPlugin::new(
identity, identity,
PluginGcConfig { PluginGcConfig {
enabled: true, enabled: true,
stop_after: 0, stop_after: 0,
}, },
None,
)); ));
let interface = plugin.clone().get_plugin(Some((engine_state, stack)))?; let interface = plugin.clone().get_plugin(Some((engine_state, stack)))?;
let metadata = interface.get_metadata()?; let metadata = interface.get_metadata()?;

View File

@ -3838,7 +3838,7 @@ pub fn parse_register(working_set: &mut StateWorkingSet, lite_command: &LiteComm
let metadata_and_signatures = plugin let metadata_and_signatures = plugin
.clone() .clone()
.get(get_envs, None) .get(get_envs)
.and_then(|p| { .and_then(|p| {
let meta = p.get_metadata()?; let meta = p.get_metadata()?;
let sigs = p.get_signature()?; let sigs = p.get_signature()?;

View File

@ -295,7 +295,11 @@ pub fn add_plugin_to_working_set(
// Add it to / get it from the working set // Add it to / get it from the working set
let plugin = working_set.find_or_create_plugin(identity, || { let plugin = working_set.find_or_create_plugin(identity, || {
Arc::new(PersistentPlugin::new(identity.clone(), gc_config.clone())) Arc::new(PersistentPlugin::new(
identity.clone(),
gc_config.clone(),
working_set.permanent_state.ctrlc_handlers.clone(),
))
}); });
plugin.set_gc_config(&gc_config); plugin.set_gc_config(&gc_config);

View File

@ -37,6 +37,8 @@ struct MutableState {
preferred_mode: Option<PreferredCommunicationMode>, preferred_mode: Option<PreferredCommunicationMode>,
/// Garbage collector config /// Garbage collector config
gc_config: PluginGcConfig, gc_config: PluginGcConfig,
/// TODO: docs
ctrlc_handlers: Option<ctrlc::Handlers>,
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -58,7 +60,11 @@ struct RunningPlugin {
impl PersistentPlugin { impl PersistentPlugin {
/// Create a new persistent plugin. The plugin will not be spawned immediately. /// Create a new persistent plugin. The plugin will not be spawned immediately.
pub fn new(identity: PluginIdentity, gc_config: PluginGcConfig) -> PersistentPlugin { pub fn new(
identity: PluginIdentity,
gc_config: PluginGcConfig,
ctrlc_handlers: Option<ctrlc::Handlers>,
) -> PersistentPlugin {
PersistentPlugin { PersistentPlugin {
identity, identity,
mutable: Mutex::new(MutableState { mutable: Mutex::new(MutableState {
@ -66,6 +72,7 @@ impl PersistentPlugin {
metadata: None, metadata: None,
preferred_mode: None, preferred_mode: None,
gc_config, gc_config,
ctrlc_handlers,
}), }),
} }
} }
@ -77,7 +84,6 @@ impl PersistentPlugin {
pub fn get( pub fn get(
self: Arc<Self>, self: Arc<Self>,
envs: impl FnOnce() -> Result<HashMap<String, String>, ShellError>, envs: impl FnOnce() -> Result<HashMap<String, String>, ShellError>,
ctrlc_handlers: Option<ctrlc::Handlers>,
) -> Result<PluginInterface, ShellError> { ) -> Result<PluginInterface, ShellError> {
let mut mutable = self.mutable.lock().map_err(|_| ShellError::NushellFailed { let mut mutable = self.mutable.lock().map_err(|_| ShellError::NushellFailed {
msg: format!( msg: format!(
@ -99,9 +105,7 @@ impl PersistentPlugin {
// TODO: We should probably store the envs somewhere, in case we have to launch without // TODO: We should probably store the envs somewhere, in case we have to launch without
// envs (e.g. from a custom value) // envs (e.g. from a custom value)
let envs = envs()?; let envs = envs()?;
let result = self let result = self.clone().spawn(&envs, &mut mutable);
.clone()
.spawn(&envs, &mut mutable, ctrlc_handlers.clone());
// Check if we were using an alternate communication mode and may need to fall back to // Check if we were using an alternate communication mode and may need to fall back to
// stdio. // stdio.
@ -116,7 +120,7 @@ impl PersistentPlugin {
mutable.preferred_mode); mutable.preferred_mode);
// Reset to stdio and try again, but this time don't catch any error // Reset to stdio and try again, but this time don't catch any error
mutable.preferred_mode = Some(PreferredCommunicationMode::Stdio); mutable.preferred_mode = Some(PreferredCommunicationMode::Stdio);
self.clone().spawn(&envs, &mut mutable, ctrlc_handlers)?; self.clone().spawn(&envs, &mut mutable)?;
} }
Ok(mutable Ok(mutable
@ -135,7 +139,6 @@ impl PersistentPlugin {
self: Arc<Self>, self: Arc<Self>,
envs: &HashMap<String, String>, envs: &HashMap<String, String>,
mutable: &mut MutableState, mutable: &mut MutableState,
ctrlc_handlers: Option<ctrlc::Handlers>,
) -> Result<(), ShellError> { ) -> Result<(), ShellError> {
// Make sure `running` is set to None to begin // Make sure `running` is set to None to begin
if let Some(running) = mutable.running.take() { if let Some(running) = mutable.running.take() {
@ -214,10 +217,12 @@ impl PersistentPlugin {
gc.stop_tracking(); gc.stop_tracking();
// Set the mode and try again // Set the mode and try again
mutable.preferred_mode = Some(PreferredCommunicationMode::LocalSocket); mutable.preferred_mode = Some(PreferredCommunicationMode::LocalSocket);
return self.spawn(envs, mutable, ctrlc_handlers); return self.spawn(envs, mutable);
} }
let guard = ctrlc_handlers let guard = mutable
.ctrlc_handlers
.as_mut()
.map(|ctrlc_handlers| { .map(|ctrlc_handlers| {
let interface = interface.clone(); let interface = interface.clone();
ctrlc_handlers.register(Box::new(move || { ctrlc_handlers.register(Box::new(move || {
@ -229,7 +234,7 @@ impl PersistentPlugin {
mutable.running = Some(RunningPlugin { mutable.running = Some(RunningPlugin {
interface, interface,
gc, gc,
_ctrlc_guard: guard, _ctrlc_guard: guard.clone(),
}); });
Ok(()) Ok(())
} }
@ -335,11 +340,7 @@ impl GetPlugin for PersistentPlugin {
self: Arc<Self>, self: Arc<Self>,
mut context: Option<(&EngineState, &mut Stack)>, mut context: Option<(&EngineState, &mut Stack)>,
) -> Result<PluginInterface, ShellError> { ) -> Result<PluginInterface, ShellError> {
let ctrlc_handlers = context self.get(|| {
.as_ref()
.and_then(|(engine_state, _)| engine_state.ctrlc_handlers.clone());
self.get(
|| {
// Get envs from the context if provided. // Get envs from the context if provided.
let envs = context let envs = context
.as_mut() .as_mut()
@ -353,8 +354,6 @@ impl GetPlugin for PersistentPlugin {
.transpose()?; .transpose()?;
Ok(envs.unwrap_or_default()) Ok(envs.unwrap_or_default())
}, })
ctrlc_handlers,
)
} }
} }

View File

@ -11,6 +11,14 @@ pub struct Handlers {
next_id: Arc<Sequence>, next_id: Arc<Sequence>,
} }
impl Debug for Handlers {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Handlers")
.field("next_id", &self.next_id)
.finish()
}
}
#[derive(Clone)] #[derive(Clone)]
pub struct Guard { pub struct Guard {
id: usize, id: usize,