cyfs_util/process/
daemon.rs

1#[cfg(unix)]
2pub mod daemon {
3    use cyfs_base::BuckyError;
4
5    use std::process::{exit, Command};
6
7    use nix::{
8        sys::wait::{waitpid, WaitStatus},
9        unistd::{fork, setsid, ForkResult},
10    };
11
12    pub fn launch_as_daemon(cmd_line: &str) -> Result<(), BuckyError> {
13        let ret = unsafe { fork() }.map_err(|e| {
14            let msg = format!("fork error: {}", e);
15            error!("{}", msg);
16
17            BuckyError::from(msg)
18        })?;
19
20        match ret {
21            ForkResult::Parent { child } => {
22                info!("fork child as daemon success: {}", child);
23
24                match waitpid(child, None) {
25                    Ok(status) => {
26                        info!("fork child exit: {} {:?}", child, status);
27                        if let WaitStatus::Exited(_pid, code) = status {
28                            if code == 0 {
29                                return Ok(());
30                            }
31                        }
32
33                        let msg = format!("fork child but wait error: {}, {:?}", child, status);
34                        error!("{}", msg);
35
36                        Err(BuckyError::from(msg))
37                    }
38                    Err(e) => {
39                        let msg = format!("fork child wait error: {} {}", child, e);
40                        error!("{}", msg);
41
42                        Err(BuckyError::from(msg))
43                    }
44                }
45            }
46
47            ForkResult::Child => {
48                match setsid() {
49                    Ok(sid) => {
50                        info!("new sid: {}", sid);
51                    }
52                    Err(e) => {
53                        error!("setsid error: {}", e);
54                        exit(1);
55                    }
56                }
57
58                let mut parts: Vec<&str> = crate::ProcessUtil::parse_cmd(cmd_line);
59                assert!(parts.len() > 0);
60
61                let mut cmd = Command::new(parts[0]);
62                if parts.len() > 1 {
63                    parts.remove(0);
64                    cmd.args(&parts);
65                }
66
67                let code = match cmd.spawn() {
68                    Ok(_) => {
69                        info!("spawn daemon success!");
70                        0
71                    }
72                    Err(err) => {
73                        error!("spawn daemon error: {}", err);
74                        1
75                    }
76                };
77
78                exit(code);
79            }
80        }
81    }
82}
83
84#[cfg(windows)]
85pub mod daemon {
86    use cyfs_base::BuckyError;
87    use std::process::{Command, Stdio};
88
89    pub fn launch_as_daemon(cmd_line: &str) -> Result<(), BuckyError> {
90        let mut parts: Vec<&str> = crate::ProcessUtil::parse_cmd(cmd_line);
91        assert!(parts.len() > 0);
92
93        let mut cmd = Command::new(parts[0]);
94        if parts.len() > 1 {
95            parts.remove(0);
96            cmd.args(&parts);
97        }
98
99        crate::ProcessUtil::detach(&mut cmd);
100
101        cmd.stdin(Stdio::null())
102            .stdout(Stdio::null())
103            .stderr(Stdio::null());
104
105        match cmd.spawn() {
106            Ok(_) => {
107                info!("spawn as daemon success: {}", cmd_line);
108
109                Ok(())
110            }
111            Err(err) => {
112                let msg = format!("spawn as daemon error: {} {}", cmd_line, err);
113                error!("{}", msg);
114
115                Err(BuckyError::from(msg))
116            }
117        }
118    }
119}