pidfile(3bsd)
π pidfile β the 3bsd manual page, bestie edition π
okay so you know how daemons need to leave a lil note saying "hey, I'm alive, this is my PID"? that's literally this whole page. welcome to pidfile(3bsd), from the LOCAL section, no cap β¨
πΈ NAME πΈ
pidfile_open, pidfile_write, pidfile_close, pidfile_remove, pidfile_fileno β library for PID files handling
π LIBRARY π
Utility functions from BSD systems (libbsd, -lbsd)
β¨ SYNOPSIS β¨
#include <libutil.h>
(See libbsd(7) for include usage.)
struct pidfh *
pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
int
pidfile_write(struct pidfh *pfh);
int
pidfile_close(struct pidfh *pfh);
int
pidfile_remove(struct pidfh *pfh);
int
pidfile_fileno(struct pidfh *pfh);
π¦ DESCRIPTION π¦
The pidfile family of functions lets daemons handle PID files, bestie. It uses flopen(3bsd) to lock a pidfile and detect already running daemons β it's giving lock first, ask questions later π
The pidfile_open() function opens (or creates) a file specified by the path argument and locks it. If the pidptr argument is not NULL and the file can not be locked, the function will use it to store a PID of an already running daemon or -1 in case the daemon did not write its PID yet. The function does not write process' PID into the file here, so it can be used before fork()ing and exit with a proper error message when needed. If the path argument is NULL, /var/run/β¨prognameβ©.pid file will be used. The pidfile_open() function sets the O_CLOEXEC close-on-exec flag when opening the pidfile.
The pidfile_write() function writes process' PID into a previously opened file. The file is truncated before write, so calling the pidfile_write() function multiple times is supported. (yes bestie, you can call it again, it's not a one-time thing π)
The pidfile_close() function closes a pidfile. It should be used after daemon fork()s to start a child process.
The pidfile_remove() function closes and removes a pidfile.
The pidfile_fileno() function returns the file descriptor for the open pidfile.
π RETURN VALUES π
The pidfile_open() function returns a valid pointer to a pidfh structure on success, or NULL if an error occurs. If an error occurs, errno will be set.
The pidfile_write(), pidfile_close(), and pidfile_remove() functions return the value 0 if successful; otherwise the value -1 is returned and the global variable errno is set to indicate the error.
The pidfile_fileno() function returns the low-level file descriptor. It returns -1 and sets errno if a NULL pidfh is specified, or if the pidfile is no longer open.
π EXAMPLES π
The following example shows in which order these functions should be used. Note that it is safe to pass NULL to pidfile_write(), pidfile_remove(), pidfile_close() and pidfile_fileno() functions.
not me pointing out that NULL-safety is the whole vibe here β it's giving "handles it, no drama" π«Ά
struct pidfh *pfh;
pid_t otherpid, childpid;
pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
if (pfh == NULL) {
if (errno == EEXIST) {
errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
(intmax_t)otherpid);
}
/* If we cannot create pidfile from other reasons, only warn. */
warn("Cannot open or create pidfile");
/*
* Even though pfh is NULL we can continue, as the other pidfile_*
* function can handle such situation by doing nothing except setting
* errno to EINVAL.
*/
}
if (daemon(0, 0) == -1) {
warn("Cannot daemonize");
pidfile_remove(pfh);
exit(EXIT_FAILURE);
}
pidfile_write(pfh);
for (;;) {
/* Do work. */
childpid = fork();
switch (childpid) {
case -1:
syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
break;
case 0:
pidfile_close(pfh);
/* Do child work. */
break;
default:
syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
break;
}
}
pidfile_remove(pfh);
exit(EXIT_SUCCESS);
π ERRORS π
The pidfile_open() function will fail if:
[EEXIST]β Some process already holds the lock on the given pidfile, meaning that a daemon is already running. If pidptr argument is notNULLthe function will use it to store a PID of an already running daemon or-1in case daemon did not write its PID yet.[ENAMETOOLONG]β Specified pidfile's name is too long.[EINVAL]β Some process already holds the lock on the given pidfile, but PID read from there is invalid.
The pidfile_open() function may also fail and set errno for any errors specified for the fstat(2), open(2), and read(2) calls.
The pidfile_write() function will fail if:
[EINVAL]β Improper function use. Probably called beforepidfile_open().
The pidfile_write() function may also fail and set errno for any errors specified for the fstat(2), ftruncate(2), and write(2) calls.
The pidfile_close() function may fail and set errno for any errors specified for the close(2) and fstat(2) calls.
The pidfile_remove() function will fail if:
[EINVAL]β Improper function use. Probably called not from the process which madepidfile_write().
The pidfile_remove() function may also fail and set errno for any errors specified for the close(2), fstat(2), write(2), and unlink(2) system calls and the flopen(3bsd) library function.
The pidfile_fileno() function will fail if:
[EINVAL]β Improper function use. Probably called not from the process which usedpidfile_open().
fr fr, that EINVAL is just the library going "bestie, wrong order, read the room" π
π SEE ALSO π
open(2), daemon(3), flopen(3bsd)
π§ HISTORY π§
The functions pidfile_open(), pidfile_write(), pidfile_close() and pidfile_remove() first appeared in FreeBSD 5.5.
The function pidfile_fileno() first appeared in FreeBSD 10.0.
π AUTHORS π
The pidfile functionality is based on ideas from John-Mark Gurney <jmg@FreeBSD.org>.
The code and manual page was written by Pawel Jakub Dawidek <pjd@FreeBSD.org>.
and that's the whole page, bestie β icon behaviour, ate, no notes π β¨
this lil cutie came from the Debian packaging, dated February 8, 2012, and it's the pidfile(3bsd) page π bye mwah π«Ά
π¦ where this page comes from
- alpine 3.22: libbsd-doc 0.12.2-r0 Β· BSD-3-Clause
- alpine 3.23: libbsd-doc 0.12.2-r0 Β· BSD-3-Clause
- alpine 3.24: libbsd-doc 0.12.2-r0 Β· BSD-3-Clause
- arch rolling: libbsd 0.12.2-2 Β· custom
- debian trixie: libbsd-dev 0.12.2-2
- epel 10: libbsd-devel 0.12.2-4.el10_0 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- epel 9: libbsd-devel 0.12.2-1.el9 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 43: libbsd-devel 0.12.2-6.fc43 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 43: libbsd-devel 0.12.2-6.fc43 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 44: libbsd-devel 0.12.2-7.fc44 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- fedora 44: libbsd-devel 0.12.2-7.fc44 Β· Beerware AND BSD-2-Clause AND BSD-3-Clause AND ISC AND libutil-David-Nugent AND MIT AND LicenseRef-Fedora-Public-Domain
- nixos 26.05: libbsd 0.12.2
- nixpkgs unstable: libbsd 0.12.2
- ubuntu noble: libbsd-dev 0.12.1-1build1
- ubuntu noble: libbsd-dev 0.12.1-1build1.1
- ubuntu questing: libbsd-dev 0.12.2-2build1
- ubuntu resolute: libbsd-dev 0.12.2-2build2
- ubuntu stonking: libbsd-dev 0.12.2-3
- Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms