Not ideal: yes. Obsolete? Not sure. Maybe under Linux it's obsolete now, but it's pretty common on other Unix-like operating systems at the time of this writing. (Maybe these are of no concern for the OP, but I think it's good practice to write platform-independent where possible and where it's not too much effort.)
Under Linux: Maybe. But, for example, FreeBSD doesn't ship with dbus in its base system. You can install it as a package. Relying on dbus will add extra dependencies for your software. I don't think most services require dbus. (edit: And I think DBUS is more targeted for Desktop environments, hence the "D"?)
I'm not really sure what daemon()
does exactly, but looks like it also doesn't fork under (Free)BSD either (see edit below) (man 3 daemon
on FreeBSD). Not sure though. Regarding pidfiles: At least under BSD, they seem to be heavily used yet.
I guess the documentation for the pidfile_
C functions still covers the "old way" of forking, though.
So it matters on how your process daemonizes. Looks like forking isn't necessary anymore. But if, during the daemonization process, your PID changes (depending on how you do it), then you want to determine/write the PID after that process, so that the PID file contains the actual process ID of your daemon.
Edit: Actually invoking the daemon
C function does change the PID on my system. So I guess it forks internally. Tested with this program:
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main() {
printf("PID before daemonizing: %i\n", (int)getpid());
if (daemon(1, 1)) {
perror("could not daemonize");
}
printf("PID after daemonizing: %i\n", (int)getpid());
return 0;
}
Coming back to your problem:
I think the easiest way would be advisory file locks (as @cuviper suggested by pointing to what cargo
does). AFAIK, these will fail to protect you if your data is on an NFS share. From the above linked cargo
source:
// File locking on Unix is currently implemented via `flock`, which is known
// to be broken on NFS. We could in theory just ignore errors that happen on
// NFS, but apparently the failure mode [1] for `flock` on NFS is **blocking
// forever**, even if the "non-blocking" flag is passed!
//
// As a result, we just skip all file locks entirely on NFS mounts. That
// should avoid calling any `flock` functions at all, and it wouldn't work
// there anyway.
//
// [1]: https://github.com/rust-lang/cargo/issues/2615
if is_on_nfs_mount(path) {
return Ok(());
}
(source)
I (personally) think that also the pidfile approach is reasonable (which is "basically" a lock file, with some extra contents: the PID). In addition to (or, on NFS, as an alternative?) acquiring a lock, you could also check its contents and test if a process with the given PID is still running. Thus, even if the locking fails (e.g. due to a weird network file system), you can get a warning that an instance of the process may be still running. You could then provide a command-line option to wipe out the pidfile. But not sure if that's worth the effort.
Of course, you could also rely on a third service, such as DBUS, or possibly any other form of interprocess communication, e.g. System V interprocess communication semaphores. I don't think the latter would be idiomatic though (it's rather exotic, nowadays, I believe).