1use crate::context::PluginContext;
8use crate::log_plugin::{EVENT_PLUG_DOWN_PREFIX, LOG_LEVEL_ERROR, LOG_LEVEL_WARN};
9use crate::plugin::{PANIC_LIMIT, Plugin};
10use crate::registry::{EntryStats, PluginStateCell, PluginStateCode};
11use crossbeam_channel::Receiver;
12use ek_event::{Event, EventEngine};
13use std::panic::{AssertUnwindSafe, catch_unwind};
14use std::sync::atomic::Ordering;
15use std::sync::Arc;
16use std::thread::JoinHandle;
17
18pub(crate) fn spawn_worker(
19 plugin: Arc<dyn Plugin>,
20 rx: Receiver<Event>,
21 state: PluginStateCell,
22 stats: Arc<EntryStats>,
23 ctx: Arc<PluginContext>,
24 bus: Arc<EventEngine>,
25) -> JoinHandle<()> {
26 let name = plugin.name().to_string();
27 std::thread::Builder::new()
28 .name(format!("ek-worker.{name}"))
29 .spawn(move || worker_loop(plugin, rx, state, stats, ctx, bus))
30 .expect("ek-core: spawn worker thread")
31}
32
33fn worker_loop(
34 plugin: Arc<dyn Plugin>,
35 rx: Receiver<Event>,
36 state: PluginStateCell,
37 stats: Arc<EntryStats>,
38 ctx: Arc<PluginContext>,
39 bus: Arc<EventEngine>,
40) {
41 let mut consecutive: u64 = 0;
44 loop {
45 match rx.recv() {
46 Ok(event) => {
47 let result = catch_unwind(AssertUnwindSafe(|| plugin.on_mail(&event)));
48 match result {
49 Ok(()) => consecutive = 0,
50 Err(_panic) => {
51 consecutive += 1;
52 let _ = stats.panics.fetch_add(1, Ordering::AcqRel);
53 if consecutive >= PANIC_LIMIT as u64 {
54 if state.cas(PluginStateCode::Running, PluginStateCode::Quarantined) {
55 ctx.write_log(
56 LOG_LEVEL_ERROR,
57 &format!(
58 "plugin {:?} quarantined after {} consecutive handler panics",
59 plugin.name(),
60 consecutive
61 ),
62 );
63 let _ = bus.put(Event::new(format!(
65 "{EVENT_PLUG_DOWN_PREFIX}{}",
66 plugin.name()
67 )));
68 }
69 break;
71 }
72 ctx.write_log(
73 LOG_LEVEL_WARN,
74 &format!(
75 "plugin {:?} handler panicked ({consecutive}/{PANIC_LIMIT})",
76 plugin.name()
77 ),
78 );
79 }
80 }
81 drop(event);
83 }
84 Err(_disconnected) => {
86 state.finish();
87 break;
88 }
89 }
90 }
91 stats.done.store(true, Ordering::Release);
92}