agent_procs/daemon/
spawn.rs1use crate::paths;
2use std::fs;
3use std::path::Path;
4use std::process::Command;
5
6pub fn spawn_daemon(session: &str) -> std::io::Result<()> {
10 let socket_dir = paths::socket_base_dir();
12 fs::create_dir_all(&socket_dir)?;
13 #[cfg(unix)]
15 {
16 use std::os::unix::fs::PermissionsExt;
17 fs::set_permissions(&socket_dir, fs::Permissions::from_mode(0o700))?;
18 }
19
20 let state = paths::state_dir(session);
21 fs::create_dir_all(state.join("logs"))?;
22
23 let socket_path = paths::socket_path(session);
24 let pid_path = paths::pid_path(session);
25
26 let _ = fs::remove_file(&socket_path);
28
29 let exe = std::env::current_exe()?;
31
32 let child = Command::new(&exe)
34 .args(["run-daemon", session])
35 .stdin(std::process::Stdio::null())
36 .stdout(std::process::Stdio::null())
37 .stderr(std::process::Stdio::null())
38 .spawn()?;
39
40 drop(child);
43
44 wait_for_daemon_ready(&pid_path, &socket_path)
45}
46
47fn wait_for_daemon_ready(pid_path: &Path, socket_path: &Path) -> std::io::Result<()> {
48 for _ in 0..100 {
50 if pid_path.exists() && socket_path.exists() {
51 if std::os::unix::net::UnixStream::connect(socket_path).is_ok() {
53 return Ok(());
54 }
55 }
56 std::thread::sleep(std::time::Duration::from_millis(50));
57 }
58 Err(std::io::Error::new(
59 std::io::ErrorKind::TimedOut,
60 "daemon did not start within 5s",
61 ))
62}
63
64pub async fn run_daemon(session: &str) {
67 {
71 use tracing_subscriber::{EnvFilter, fmt};
72
73 let log_file = paths::state_dir(session).join("daemon.log");
74 let _ = std::fs::create_dir_all(paths::state_dir(session));
76 if let Ok(file) = std::fs::File::create(&log_file) {
77 let subscriber = fmt()
78 .with_env_filter(
79 EnvFilter::from_default_env()
80 .add_directive("agent_procs=info".parse().unwrap()),
81 )
82 .with_writer(file)
83 .with_ansi(false)
84 .finish();
85 let _ = tracing::subscriber::set_global_default(subscriber);
86 }
87 }
88
89 let socket_path = paths::socket_path(session);
90 let pid_path = paths::pid_path(session);
91
92 let socket_dir = paths::socket_base_dir();
94 let _ = std::fs::create_dir_all(&socket_dir);
95 #[cfg(unix)]
96 {
97 use std::os::unix::fs::PermissionsExt;
98 let _ = std::fs::set_permissions(&socket_dir, std::fs::Permissions::from_mode(0o700));
99 }
100 let state = paths::state_dir(session);
101 let _ = std::fs::create_dir_all(state.join("logs"));
102
103 if let Ok(mut f) = std::fs::File::create(&pid_path) {
105 use std::io::Write;
106 let _ = writeln!(f, "{}", std::process::id());
107 }
108
109 super::server::run(session, &socket_path).await;
110
111 let _ = std::fs::remove_file(&socket_path);
112 let _ = std::fs::remove_file(&pid_path);
113}