Creating Daemon Processes

I am writing a server and need to be able to run it as a daemon. I began writing the server some time ago; when I did, the daemonize crate served me just fine. But as I've come back to this project, daemonize is no longer working at all: the compiler signals a number of errors now. Any thoughts on where to turn for crates that might replace daemonize?

What are the compiler errors?

Here's what the compiler has to say when it tries to compile daemonize:
Checking daemonize v0.4.1
Compiling syn v1.0.107
Checking parking_lot v0.12.1
error[E0433]: failed to resolve: could not find unix in os
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:58:14
|
58 | use std::os::unix::ffi::OsStringExt;
| ^^^^ could not find unix in os

error[E0433]: failed to resolve: could not find unix in os
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:59:14
|
59 | use std::os::unix::io::AsRawFd;
| ^^^^ could not find unix in os

error[E0432]: unresolved imports libc::fork, libc::ftruncate, libc::setgid, libc::setsid, libc::setuid, libc::umask, libc::LOCK_EX, libc::LOCK_NB
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:65:25
|
65 | c_int, close, dup2, fork, ftruncate, getpid, open, setgid, setsid, setuid, umask, write,
| ^^^^ ^^^^^^^^^ ^^^^^^ ^^^^^^ ^^^^^^ ^^^^^ no umask in the root
| | | | | |
| | | | | no setuid in the root
| | | | no setsid in the root
| | | no setgid in the root
| | no ftruncate in the root
| no fork in the root
66 | LOCK_EX, LOCK_NB,
| ^^^^^^^ ^^^^^^^ no LOCK_NB in the root
| |
| no LOCK_EX in the root
|
help: a similar name exists in the module
|
65 | c_int, close, dup2, fork, strncat, getpid, open, setgid, setsid, setuid, umask, write,
| ~~~~~~~
help: a similar name exists in the module
|
65 | c_int, close, dup2, fork, ftruncate, getpid, open, getpid, setsid, setuid, umask, write,
| ~~~~~~
help: a similar name exists in the module
|
65 | c_int, close, dup2, fork, ftruncate, getpid, open, setgid, getpid, setuid, umask, write,
| ~~~~~~
help: a similar name exists in the module
|
65 | c_int, close, dup2, fork, ftruncate, getpid, open, setgid, setsid, getpid, umask, write,
| ~~~~~~

error[E0432]: unresolved imports libc::gid_t, libc::mode_t, libc::uid_t
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:68:16
|
68 | pub use libc::{gid_t, mode_t, uid_t};
| ^^^^^ ^^^^^^ ^^^^^ no uid_t in the root
| | |
| | no mode_t in the root
| no gid_t in the root

error[E0412]: cannot find type uid_t in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\ffi.rs:18:19
|
18 | pw_uid: libc::uid_t,
| ^^^^^ not found in libc

error[E0412]: cannot find type gid_t in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\ffi.rs:19:19
|
19 | pw_gid: libc::gid_t,
| ^^^^^ not found in libc

error[E0412]: cannot find type gid_t in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\ffi.rs:30:19
|
30 | gr_gid: libc::gid_t,
| ^^^^^ not found in libc

error[E0412]: cannot find type gid_t in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\ffi.rs:41:63
|
41 | pub unsafe fn get_gid_by_name(name: &CString) -> Optionlibc::gid_t {
| ^^^^^ not found in libc

error[E0412]: cannot find type uid_t in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\ffi.rs:51:63
|
51 | pub unsafe fn get_uid_by_name(name: &CString) -> Optionlibc::uid_t {
| ^^^^^ not found in libc

error[E0425]: cannot find value STDIN_FILENO in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:466:25
|
466 | process_stdio(libc::STDIN_FILENO, stdin)?;
| ^^^^^^^^^^^^ not found in libc

error[E0425]: cannot find value STDOUT_FILENO in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:467:25
|
467 | process_stdio(libc::STDOUT_FILENO, stdout)?;
| ^^^^^^^^^^^^^ not found in libc

error[E0425]: cannot find value STDERR_FILENO in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:468:25
|
468 | process_stdio(libc::STDERR_FILENO, stderr)?;
| ^^^^^^^^^^^^^ not found in libc

error[E0425]: cannot find function chown in crate libc
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:527:15
|
527 | libc::chown(path_c.as_ptr(), uid, gid),
| ^^^^^ not found in libc

error[E0283]: type annotations needed: cannot satisfy User: From<&'a str>
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:177:10
|
177 | impl<'a> From<&'a str> for User {
| ^^^^^^^^^^^^^
|
note: multiple impls satisfying User: From<&'a str> found
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:177:1
|
177 | impl<'a> From<&'a str> for User {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
183 | impl From<uid_t> for User {
| ^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0283]: type annotations needed: cannot satisfy Group: From<&'a str>
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:196:10
|
196 | impl<'a> From<&'a str> for Group {
| ^^^^^^^^^^^^^
|
note: multiple impls satisfying Group: From<&'a str> found
--> C:\Users\hdpre.cargo\registry\src\github.com-1ecc6299db9ec823\daemonize-0.4.1\src\lib.rs:196:1
|
196 | impl<'a> From<&'a str> for Group {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
...
202 | impl From<gid_t> for Group {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

Some errors have detailed explanations: E0283, E0412, E0425, E0432, E0433.
For more information about an error, try rustc --explain E0283.
error: could not compile daemonize due to 15 previous errors
warning: build failed, waiting for other jobs to finish...

Well, daemonize, it seems, will only work on Unix-like OS's, like Linux, Mac and BSD. And you're now trying it on Windows...

Hmm. I'm actually uploading my source file to a Ubuntu cloud server and compiling it there (I only have a Windows machine personally, so I can't test it in Linux). But a number of those errors--particularly related to the traits and missing imports--don't llook much like they're related to the OS I'm checking the source file on.

I would recommend against using that crate on modern Linux systems, that style of creating forking daemons is obsolete. See the "New-Style Daemons" section in man 7 daemon for a description of how things are done now. You can just write the program normally and log to stderr, any special requirements would go in a systemd unit file.

6 Likes

You could also control the daemon using OS tech like systemd and Windows scheduler. At least that would let you test on Windows using its daemon technology, and run in production on systemd-enabled *nix

Yes, for more advanced functionality there is the systemd crate. And for Windows there is windows-service.

They are, for example the reason it can't find libc::fork is because it doesn't exist on Windows. The From<&'a str> errors seem unrelated, but that's just the compiler getting confused because libc::uid_t doesn't exist on Windows, there's no actual problem with the From<&'a str> impls. I filed an issue regarding the bad error message, the compiler shouldn't be complaining about them.

Note that systemd is not part of the OS. I have employers that actively avoid it.

Systemd is the default in stock Ubuntu, so it should be fine to use it there. For other Linux distributions with other service managers, or for BSD, the forking style of daemon is also obsolete. The only place where it was used was sysvinit, but even for that a supervisor process should still be used to eliminate the need for forking/daemonizing the process. Just some of the problems with the forking approach: It is a security risk to require all services to drop privileges, and PID files are racy and error-prone, and it is both racy and a security risk for services to try to do socket activation by themselves, etc...

Do you know any crate that uses this "new" style of daemonization? Handling all the syscalls manually is a lot more harder

No crate is needed. In the new style, you don't do any of those syscalls in the daemon. Those are all handled by the service manager. It is more secure that way, because most of those syscalls require root.

1 Like

If you are on a 'nix type system you should read the manpage @jfrancis suggested.

man 7 daemon
1 Like