This commit is contained in:
Andy Gayton 2024-06-21 16:16:00 -04:00
parent 0e0d5b9201
commit c88b4dc52e
3 changed files with 60 additions and 21 deletions

View File

@ -1,5 +1,5 @@
use crate::PersistentPlugin;
use nu_protocol::{PluginGcConfig, RegisteredPlugin};
use nu_protocol::{engine::ctrlc, PluginGcConfig, RegisteredPlugin};
use std::{
sync::{mpsc, Arc, Weak},
thread,
@ -14,6 +14,7 @@ use std::{
#[derive(Debug, Clone)]
pub struct PluginGc {
sender: mpsc::Sender<PluginGcMsg>,
_ctrlc_guard: Arc<Option<ctrlc::HandlerGuard>>,
}
impl PluginGc {
@ -21,6 +22,7 @@ impl PluginGc {
pub fn new(
config: PluginGcConfig,
plugin: &Arc<PersistentPlugin>,
ctrlc_handlers: Option<ctrlc::CtrlcHandlers>,
) -> std::io::Result<PluginGc> {
let (sender, receiver) = mpsc::channel();
@ -37,7 +39,14 @@ impl PluginGc {
.name(format!("plugin gc ({})", plugin.identity().name()))
.spawn(move || state.run(receiver))?;
Ok(PluginGc { sender })
let guard = ctrlc_handlers.map(|ctrlc_handlers| {
let sender = sender.clone();
ctrlc_handlers.add(Box::new(move || {
let _ = sender.send(PluginGcMsg::Ctrlc);
}))
});
Ok(PluginGc { sender, _ctrlc_guard: Arc::new(guard) })
}
/// Update the garbage collector config

View File

@ -1,5 +1,4 @@
use crate::{
gc::PluginGcMsg,
init::{create_command, make_plugin_interface},
PluginGc,
};
@ -180,14 +179,7 @@ impl PersistentPlugin {
})?;
// Start the plugin garbage collector
let gc = PluginGc::new(mutable.gc_config.clone(), &self)?;
if let Some(ref ctrlc_handlers) = ctrlc_handlers {
let tx = gc.clone_sender();
ctrlc_handlers.add(Box::new(move || {
let _ = tx.send(PluginGcMsg::Ctrlc);
}));
}
let gc = PluginGc::new(mutable.gc_config.clone(), &self, ctrlc_handlers.clone())?;
let pid = child.id();
let interface = make_plugin_interface(

View File

@ -1,34 +1,72 @@
use std::sync::{Arc, Mutex};
use std::fmt::Debug;
use std::sync::{
atomic::{AtomicUsize, Ordering},
Arc, Mutex,
};
type CtrlcHandler = Box<dyn Fn() + Send + Sync>;
#[derive(Clone)]
pub struct CtrlcHandlers {
handlers: Arc<Mutex<Vec<CtrlcHandler>>>,
handlers: Arc<Mutex<Vec<(usize, CtrlcHandler)>>>,
next_id: Arc<AtomicUsize>,
}
#[derive(Clone)]
pub struct HandlerGuard {
id: usize,
handlers: Arc<Mutex<Vec<(usize, CtrlcHandler)>>>,
}
impl Drop for HandlerGuard {
fn drop(&mut self) {
if let Ok(mut handlers) = self.handlers.lock() {
handlers.retain(|(id, _)| *id != self.id);
}
}
}
impl Debug for HandlerGuard {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("HandlerGuard")
.field("id", &self.id)
.finish()
}
}
impl CtrlcHandlers {
pub fn new() -> CtrlcHandlers {
CtrlcHandlers {
handlers: Arc::new(Mutex::new(vec![])),
}
let handlers = Arc::new(Mutex::new(vec![]));
let next_id = Arc::new(AtomicUsize::new(0));
CtrlcHandlers { handlers, next_id }
}
pub fn add(&self, handler: CtrlcHandler) {
if let Some(mut handlers) = self.handlers.lock().ok() {
handlers.push(handler);
pub fn add(&self, handler: CtrlcHandler) -> HandlerGuard {
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
if let Ok(mut handlers) = self.handlers.lock() {
handlers.push((id, handler));
}
HandlerGuard {
id,
handlers: Arc::clone(&self.handlers),
}
}
pub fn run(&self) {
if let Some(handlers) = self.handlers.lock().ok() {
for handler in handlers.iter() {
if let Ok(handlers) = self.handlers.lock() {
for (_, handler) in handlers.iter() {
handler();
}
}
}
}
impl Default for CtrlcHandlers {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Debug for CtrlcHandlers {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("CtrlcHandlers")