aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin/rbw-agent/daemon.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/rbw-agent/daemon.rs')
-rw-r--r--src/bin/rbw-agent/daemon.rs50
1 files changed, 50 insertions, 0 deletions
diff --git a/src/bin/rbw-agent/daemon.rs b/src/bin/rbw-agent/daemon.rs
new file mode 100644
index 0000000..64cf298
--- /dev/null
+++ b/src/bin/rbw-agent/daemon.rs
@@ -0,0 +1,50 @@
+pub struct StartupAck {
+ writer: std::os::unix::io::RawFd,
+}
+
+impl StartupAck {
+ pub fn ack(&self) {
+ nix::unistd::write(self.writer, &[0]).unwrap();
+ nix::unistd::close(self.writer).unwrap();
+ }
+}
+
+impl Drop for StartupAck {
+ fn drop(&mut self) {
+ nix::unistd::close(self.writer).unwrap();
+ }
+}
+
+pub fn daemonize() -> StartupAck {
+ let runtime_dir = rbw::dirs::runtime_dir();
+ std::fs::create_dir_all(&runtime_dir).unwrap();
+
+ let (r, w) = nix::unistd::pipe().unwrap();
+ let res = daemonize::Daemonize::new()
+ .pid_file(runtime_dir.join("pidfile"))
+ .exit_action(move || {
+ nix::unistd::close(w).unwrap();
+ let mut buf = [0; 1];
+ nix::unistd::read(r, &mut buf).unwrap();
+ nix::unistd::close(r).unwrap();
+ })
+ .start();
+ nix::unistd::close(r).unwrap();
+
+ match res {
+ Ok(_) => (),
+ Err(e) => {
+ match e {
+ daemonize::DaemonizeError::LockPidfile(_) => {
+ // 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);
+ }
+ _ => panic!("failed to daemonize: {}", e),
+ }
+ }
+ }
+
+ StartupAck { writer: w }
+}