blob: 06db89132878168a1b3f51f36cb1e5b4f8d73a4d (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
|
pub struct StartupAck {
writer: std::os::unix::io::OwnedFd,
}
impl StartupAck {
pub fn ack(self) -> anyhow::Result<()> {
rustix::io::write(&self.writer, &[0])?;
Ok(())
}
}
pub fn daemonize() -> anyhow::Result<StartupAck> {
let stdout = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(rbw::dirs::agent_stdout_file())?;
let stderr = std::fs::OpenOptions::new()
.append(true)
.create(true)
.open(rbw::dirs::agent_stderr_file())?;
let (r, w) = rustix::pipe::pipe()?;
let daemonize = daemonize::Daemonize::new()
.pid_file(rbw::dirs::pid_file())
.stdout(stdout)
.stderr(stderr);
let res = match daemonize.execute() {
daemonize::Outcome::Parent(_) => {
drop(w);
let mut buf = [0; 1];
// unwraps are necessary because not really a good way to handle
// errors here otherwise
rustix::io::read(&r, &mut buf).unwrap();
drop(r);
std::process::exit(0);
}
daemonize::Outcome::Child(res) => res,
};
drop(r);
match res {
Ok(_) => (),
Err(e) => {
// XXX super gross, but daemonize removed the ability to match
// on specific error types for some reason?
if e.to_string().contains("unable to lock pid file") {
// this means that there is already an agent running, so
// return a special exit code to allow the cli to detect
// this case and not error out
std::process::exit(23);
} else {
panic!("failed to daemonize: {e}");
}
}
}
Ok(StartupAck { writer: w })
}
|