xref: /freebsd/lib/libutil/pidfile.3 (revision b5daf675efc746611c7cfcd1fa474b8905064c4b)
1.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
2.\" All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\"    notice, this list of conditions and the following disclaimer in the
11.\"    documentation and/or other materials provided with the distribution.
12.\"
13.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
14.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
17.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23.\" SUCH DAMAGE.
24.\"
25.Dd August 2, 2025
26.Dt PIDFILE 3
27.Os
28.Sh NAME
29.Nm pidfile_open ,
30.Nm pidfile_write ,
31.Nm pidfile_close ,
32.Nm pidfile_remove ,
33.Nm pidfile_fileno ,
34.Nm pidfile_signal
35.Nd "library for PID files handling"
36.Sh LIBRARY
37.Lb libutil
38.Sh SYNOPSIS
39.In libutil.h
40.Ft "struct pidfh *"
41.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
42.Ft int
43.Fn pidfile_write "struct pidfh *pfh"
44.Ft int
45.Fn pidfile_close "struct pidfh *pfh"
46.Ft int
47.Fn pidfile_remove "struct pidfh *pfh"
48.Ft int
49.Fn pidfile_fileno "struct pidfh *pfh"
50.Ft int
51.Fn pidfile_signal "const char *path" "int sig" "pid_t *pidptr"
52.Sh DESCRIPTION
53The
54.Nm pidfile
55family of functions allows daemons to handle PID files.
56It uses
57.Xr flopen 3
58to lock a pidfile and detect already running daemons.
59.Pp
60The
61.Fn pidfile_open
62function opens (or creates) a file specified by the
63.Fa path
64argument and locks it.
65If
66.Fa pidptr
67argument is not
68.Dv NULL
69and file can not be locked, the function will use it to store a PID of an
70already running daemon or
71.Li -1
72in case daemon did not write its PID yet.
73The function does not write process' PID into the file here, so it can be
74used before
75.Fn fork Ns ing
76and exit with a proper error message when needed.
77If the
78.Fa path
79argument is
80.Dv NULL ,
81.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
82file will be used.
83The
84.Fn pidfile_open
85function sets the O_CLOEXEC close-on-exec flag when opening the pidfile.
86.Pp
87The
88.Fn pidfile_write
89function writes process' PID into a previously opened file.
90The file is truncated before write, so calling the
91.Fn pidfile_write
92function multiple times is supported.
93.Pp
94The
95.Fn pidfile_close
96function closes a pidfile.
97It should be used after daemon
98.Fn fork Ns s
99to start a child process.
100.Pp
101The
102.Fn pidfile_remove
103function closes and removes a pidfile.
104.Pp
105The
106.Fn pidfile_fileno
107function returns the file descriptor for the open pidfile.
108.Pp
109The
110.Fn pidfile_signal
111function looks for the pidfile specified by
112.Va path ,
113and if it exists and is locked, sends the signal specified by
114.Va sig
115to the PID it contains.
116If
117.Va pidptr
118is not
119.Dv NULL ,
120the PID that was found in the pidfile is stored in the location it
121points to.
122Note that calling
123.Fn pidfile_signal
124with
125.Va sig
126set to zero is an effective way to verify the existence of a pidfile
127and of the process that owns it.
128.Sh RETURN VALUES
129The
130.Fn pidfile_open
131function returns a valid pointer to a
132.Vt pidfh
133structure on success, or
134.Dv NULL
135if an error occurs.
136If an error occurs,
137.Va errno
138will be set.
139.Pp
140.Rv -std pidfile_write pidfile_close pidfile_remove
141.Pp
142The
143.Fn pidfile_fileno
144function returns the low-level file descriptor.
145It returns
146.Li -1
147and sets
148.Va errno
149if a NULL
150.Vt pidfh
151is specified, or if the pidfile is no longer open.
152.Pp
153The
154.Fn pidfile_signal
155function returns 0 if it successfully signaled a process, and an
156appropriate
157.Va errno
158value otherwise.
159.Sh EXAMPLES
160The following example shows in which order these functions should be used.
161Note that it is safe to pass
162.Dv NULL
163to
164.Fn pidfile_write ,
165.Fn pidfile_remove ,
166.Fn pidfile_close ,
167and
168.Fn pidfile_fileno
169functions.
170.Bd -literal
171struct pidfh *pfh;
172pid_t otherpid, childpid;
173
174pfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
175if (pfh == NULL) {
176	if (errno == EEXIST) {
177		errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
178		    (intmax_t)otherpid);
179	}
180	/* If we cannot create pidfile from other reasons, only warn. */
181	warn("Cannot open or create pidfile");
182	/*
183	 * Even though pfh is NULL we can continue, as the other pidfile_*
184	 * function can handle such situation by doing nothing except setting
185	 * errno to EDOOFUS.
186	 */
187}
188
189if (daemon(0, 0) == -1) {
190	warn("Cannot daemonize");
191	pidfile_remove(pfh);
192	exit(EXIT_FAILURE);
193}
194
195pidfile_write(pfh);
196
197for (;;) {
198	/* Do work. */
199	childpid = fork();
200	switch (childpid) {
201	case -1:
202		syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
203		break;
204	case 0:
205		pidfile_close(pfh);
206		/* Do child work. */
207		break;
208	default:
209		syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
210		break;
211	}
212}
213
214pidfile_remove(pfh);
215exit(EXIT_SUCCESS);
216.Ed
217.Sh ERRORS
218The
219.Fn pidfile_open
220function will fail if:
221.Bl -tag -width Er
222.It Bq Er EEXIST
223Some process already holds the lock on the given pidfile, meaning that a
224daemon is already running.
225If
226.Fa pidptr
227argument is not
228.Dv NULL
229the function will use it to store a PID of an already running daemon or
230.Li -1
231in case daemon did not write its PID yet.
232.It Bq Er ENAMETOOLONG
233Specified pidfile's name is too long.
234.It Bq Er EINVAL
235Some process already holds the lock on the given pidfile, but PID read
236from there is invalid.
237.El
238.Pp
239The
240.Fn pidfile_open
241function may also fail and set
242.Va errno
243for any errors specified for the
244.Xr fstat 2 ,
245.Xr open 2 ,
246and
247.Xr read 2
248calls.
249.Pp
250The
251.Fn pidfile_write
252function will fail if:
253.Bl -tag -width Er
254.It Bq Er EDOOFUS
255Improper function use.
256Probably called before
257.Fn pidfile_open .
258.El
259.Pp
260The
261.Fn pidfile_write
262function may also fail and set
263.Va errno
264for any errors specified for the
265.Xr fstat 2 ,
266.Xr ftruncate 2 ,
267and
268.Xr write 2
269calls.
270.Pp
271The
272.Fn pidfile_close
273function may fail and set
274.Va errno
275for any errors specified for the
276.Xr close 2
277and
278.Xr fstat 2
279calls.
280.Pp
281The
282.Fn pidfile_remove
283function will fail if:
284.Bl -tag -width Er
285.It Bq Er EDOOFUS
286Improper function use.
287Probably called not from the process which made
288.Fn pidfile_write .
289.El
290.Pp
291The
292.Fn pidfile_remove
293function may also fail and set
294.Va errno
295for any errors specified for the
296.Xr close 2 ,
297.Xr fstat 2 ,
298.Xr write 2 ,
299and
300.Xr unlink 2
301system calls and the
302.Xr flopen 3
303library function.
304.Pp
305The
306.Fn pidfile_fileno
307function will fail if:
308.Bl -tag -width Er
309.It Bq Er EDOOFUS
310Improper function use.
311Probably called not from the process which used
312.Fn pidfile_open .
313.El
314.Pp
315The
316.Fn pidfile_signal
317function will fail if:
318.Bl -tag -width Er
319.It Bq Er ENOENT
320The pidfile does not exist, or exists but is not locked.
321.It Bq Er EDOM
322The pidfile contains a negative number.
323.El
324.Pp
325The
326.Fn pidfile_signal
327function may also fail and return any of the
328.Va errno
329values specified for the
330.Fn pidfile_read
331function and the
332.Xr kill 2
333system call.
334.Sh SEE ALSO
335.Xr kill 2 ,
336.Xr open 2 ,
337.Xr daemon 3 ,
338.Xr flopen 3
339.Sh HISTORY
340The functions
341.Fn pidfile_open ,
342.Fn pidfile_write ,
343.Fn pidfile_close ,
344and
345.Fn pidfile_remove
346first appeared in
347.Fx 5.5 .
348The
349.Fn pidfile_fileno
350function was added in
351.Fx 9.1 .
352The
353.Fn pidfile_signal
354function was added in
355.Fx 14.0 .
356.Sh AUTHORS
357.An -nosplit
358The
359.Nm pidfile
360functionality is based on ideas from
361.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
362.Pp
363The code and manual page was written by
364.An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org .
365