wip
This commit is contained in:
parent
0e0d5b9201
commit
c88b4dc52e
|
@ -1,5 +1,5 @@
|
||||||
use crate::PersistentPlugin;
|
use crate::PersistentPlugin;
|
||||||
use nu_protocol::{PluginGcConfig, RegisteredPlugin};
|
use nu_protocol::{engine::ctrlc, PluginGcConfig, RegisteredPlugin};
|
||||||
use std::{
|
use std::{
|
||||||
sync::{mpsc, Arc, Weak},
|
sync::{mpsc, Arc, Weak},
|
||||||
thread,
|
thread,
|
||||||
|
@ -14,6 +14,7 @@ use std::{
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct PluginGc {
|
pub struct PluginGc {
|
||||||
sender: mpsc::Sender<PluginGcMsg>,
|
sender: mpsc::Sender<PluginGcMsg>,
|
||||||
|
_ctrlc_guard: Arc<Option<ctrlc::HandlerGuard>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PluginGc {
|
impl PluginGc {
|
||||||
|
@ -21,6 +22,7 @@ impl PluginGc {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
config: PluginGcConfig,
|
config: PluginGcConfig,
|
||||||
plugin: &Arc<PersistentPlugin>,
|
plugin: &Arc<PersistentPlugin>,
|
||||||
|
ctrlc_handlers: Option<ctrlc::CtrlcHandlers>,
|
||||||
) -> std::io::Result<PluginGc> {
|
) -> std::io::Result<PluginGc> {
|
||||||
let (sender, receiver) = mpsc::channel();
|
let (sender, receiver) = mpsc::channel();
|
||||||
|
|
||||||
|
@ -37,7 +39,14 @@ impl PluginGc {
|
||||||
.name(format!("plugin gc ({})", plugin.identity().name()))
|
.name(format!("plugin gc ({})", plugin.identity().name()))
|
||||||
.spawn(move || state.run(receiver))?;
|
.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
|
/// Update the garbage collector config
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
gc::PluginGcMsg,
|
|
||||||
init::{create_command, make_plugin_interface},
|
init::{create_command, make_plugin_interface},
|
||||||
PluginGc,
|
PluginGc,
|
||||||
};
|
};
|
||||||
|
@ -180,14 +179,7 @@ impl PersistentPlugin {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// Start the plugin garbage collector
|
// Start the plugin garbage collector
|
||||||
let gc = PluginGc::new(mutable.gc_config.clone(), &self)?;
|
let gc = PluginGc::new(mutable.gc_config.clone(), &self, ctrlc_handlers.clone())?;
|
||||||
|
|
||||||
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 pid = child.id();
|
let pid = child.id();
|
||||||
let interface = make_plugin_interface(
|
let interface = make_plugin_interface(
|
||||||
|
|
|
@ -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>;
|
type CtrlcHandler = Box<dyn Fn() + Send + Sync>;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CtrlcHandlers {
|
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 {
|
impl CtrlcHandlers {
|
||||||
pub fn new() -> CtrlcHandlers {
|
pub fn new() -> CtrlcHandlers {
|
||||||
CtrlcHandlers {
|
let handlers = Arc::new(Mutex::new(vec![]));
|
||||||
handlers: Arc::new(Mutex::new(vec![])),
|
let next_id = Arc::new(AtomicUsize::new(0));
|
||||||
}
|
CtrlcHandlers { handlers, next_id }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add(&self, handler: CtrlcHandler) {
|
pub fn add(&self, handler: CtrlcHandler) -> HandlerGuard {
|
||||||
if let Some(mut handlers) = self.handlers.lock().ok() {
|
let id = self.next_id.fetch_add(1, Ordering::Relaxed);
|
||||||
handlers.push(handler);
|
if let Ok(mut handlers) = self.handlers.lock() {
|
||||||
|
handlers.push((id, handler));
|
||||||
|
}
|
||||||
|
HandlerGuard {
|
||||||
|
id,
|
||||||
|
handlers: Arc::clone(&self.handlers),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&self) {
|
pub fn run(&self) {
|
||||||
if let Some(handlers) = self.handlers.lock().ok() {
|
if let Ok(handlers) = self.handlers.lock() {
|
||||||
for handler in handlers.iter() {
|
for (_, handler) in handlers.iter() {
|
||||||
handler();
|
handler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for CtrlcHandlers {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for CtrlcHandlers {
|
impl std::fmt::Debug for CtrlcHandlers {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
f.debug_struct("CtrlcHandlers")
|
f.debug_struct("CtrlcHandlers")
|
||||||
|
|
Loading…
Reference in New Issue
Block a user