minidumper_child/
server.rs1use minidumper::{LoopAction, MinidumpBinary, Server, ServerHandler};
2use std::{
3 fs::{self, File},
4 io::{self, Read, Write},
5 path::{Path, PathBuf},
6 sync::atomic::AtomicBool,
7 time::Duration,
8};
9
10use crate::Error;
11
12struct Handler<Minidump, Message>
13where
14 Minidump: Fn(Vec<u8>, &Path) + Send + Sync + 'static,
15 Message: Fn(u32, Vec<u8>) + Send + Sync + 'static,
16{
17 crashes_dir: PathBuf,
18 on_minidump: Option<Minidump>,
19 on_message: Option<Message>,
20}
21
22impl<Minidump, Message> Handler<Minidump, Message>
23where
24 Minidump: Fn(Vec<u8>, &Path) + Send + Sync + 'static,
25 Message: Fn(u32, Vec<u8>) + Send + Sync + 'static,
26{
27 pub fn new(
28 crashes_dir: PathBuf,
29 on_minidump: Option<Minidump>,
30 on_message: Option<Message>,
31 ) -> Self {
32 Handler {
33 crashes_dir,
34 on_minidump,
35 on_message,
36 }
37 }
38}
39
40impl<Minidump, Message> ServerHandler for Handler<Minidump, Message>
41where
42 Minidump: Fn(Vec<u8>, &Path) + Send + Sync + 'static,
43 Message: Fn(u32, Vec<u8>) + Send + Sync + 'static,
44{
45 fn create_minidump_file(&self) -> Result<(File, PathBuf), io::Error> {
48 fs::create_dir_all(&self.crashes_dir)?;
49 let file_name = format!("{}.dmp", uuid::Uuid::new_v4());
50 let path = self.crashes_dir.join(file_name);
51 Ok((File::create(&path)?, path))
52 }
53
54 fn on_minidump_created(&self, result: Result<MinidumpBinary, minidumper::Error>) -> LoopAction {
57 if let Ok(mut minidump) = result {
58 if let Some(buffer) = minidump.contents.or_else(|| {
59 minidump.file.flush().ok().and_then(|_| {
60 let mut buf = Vec::new();
61 File::open(&minidump.path)
62 .unwrap()
63 .read_to_end(&mut buf)
64 .map(|_| buf)
65 .ok()
66 })
67 }) {
68 if let Some(on_minidump) = &self.on_minidump {
69 on_minidump(buffer, &minidump.path)
70 }
71 }
72
73 fs::remove_file(minidump.path).ok();
74 }
75
76 LoopAction::Exit
78 }
79
80 fn on_message(&self, kind: u32, buffer: Vec<u8>) {
81 if let Some(on_message) = &self.on_message {
82 on_message(kind, buffer);
83 }
84 }
85
86 fn on_client_disconnected(&self, _num_clients: usize) -> minidumper::LoopAction {
87 LoopAction::Exit
88 }
89}
90
91pub fn start<Minidump, Message>(
92 socket_name: &str,
93 crashes_dir: PathBuf,
94 stale_timeout: u64,
95 on_minidump: Option<Minidump>,
96 on_message: Option<Message>,
97) -> Result<(), Error>
98where
99 Minidump: Fn(Vec<u8>, &Path) + Send + Sync + 'static,
100 Message: Fn(u32, Vec<u8>) + Send + Sync + 'static,
101{
102 Server::with_name(socket_name)
103 .map_err(Error::from)
104 .and_then(|mut server| {
105 let handler = Box::new(Handler::new(crashes_dir, on_minidump, on_message));
106 let shutdown = AtomicBool::new(false);
107 let stale_timeout = Some(Duration::from_millis(stale_timeout));
108
109 server
110 .run(handler, &shutdown, stale_timeout)
111 .map_err(Error::from)
112 })
113}