xref: /freebsd/lib/libutil/pidfile.3 (revision fa9896e082a1046ff4fbc75fcba4d18d1f2efc19)
1412fa8f1SPawel Jakub Dawidek.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
2412fa8f1SPawel Jakub Dawidek.\" All rights reserved.
3412fa8f1SPawel Jakub Dawidek.\"
4412fa8f1SPawel Jakub Dawidek.\" Redistribution and use in source and binary forms, with or without
5412fa8f1SPawel Jakub Dawidek.\" modification, are permitted provided that the following conditions
6412fa8f1SPawel Jakub Dawidek.\" are met:
7412fa8f1SPawel Jakub Dawidek.\" 1. Redistributions of source code must retain the above copyright
8412fa8f1SPawel Jakub Dawidek.\"    notice, this list of conditions and the following disclaimer.
9412fa8f1SPawel Jakub Dawidek.\" 2. Redistributions in binary form must reproduce the above copyright
10412fa8f1SPawel Jakub Dawidek.\"    notice, this list of conditions and the following disclaimer in the
11412fa8f1SPawel Jakub Dawidek.\"    documentation and/or other materials provided with the distribution.
12412fa8f1SPawel Jakub Dawidek.\"
13412fa8f1SPawel Jakub Dawidek.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
14412fa8f1SPawel Jakub Dawidek.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15412fa8f1SPawel Jakub Dawidek.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16412fa8f1SPawel Jakub Dawidek.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
17412fa8f1SPawel Jakub Dawidek.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18412fa8f1SPawel Jakub Dawidek.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19412fa8f1SPawel Jakub Dawidek.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20412fa8f1SPawel Jakub Dawidek.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21412fa8f1SPawel Jakub Dawidek.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22412fa8f1SPawel Jakub Dawidek.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23412fa8f1SPawel Jakub Dawidek.\" SUCH DAMAGE.
24412fa8f1SPawel Jakub Dawidek.\"
25*bc89b58dSGordon Bergling.Dd May 10, 2020
26412fa8f1SPawel Jakub Dawidek.Dt PIDFILE 3
27412fa8f1SPawel Jakub Dawidek.Os
28412fa8f1SPawel Jakub Dawidek.Sh NAME
29412fa8f1SPawel Jakub Dawidek.Nm pidfile_open ,
30412fa8f1SPawel Jakub Dawidek.Nm pidfile_write ,
31412fa8f1SPawel Jakub Dawidek.Nm pidfile_close ,
32412fa8f1SPawel Jakub Dawidek.Nm pidfile_remove
336b84cd58SRuslan Ermilov.Nd "library for PID files handling"
34412fa8f1SPawel Jakub Dawidek.Sh LIBRARY
35412fa8f1SPawel Jakub Dawidek.Lb libutil
36412fa8f1SPawel Jakub Dawidek.Sh SYNOPSIS
37412fa8f1SPawel Jakub Dawidek.In libutil.h
386b84cd58SRuslan Ermilov.Ft "struct pidfh *"
39412fa8f1SPawel Jakub Dawidek.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
40412fa8f1SPawel Jakub Dawidek.Ft int
41412fa8f1SPawel Jakub Dawidek.Fn pidfile_write "struct pidfh *pfh"
42412fa8f1SPawel Jakub Dawidek.Ft int
43412fa8f1SPawel Jakub Dawidek.Fn pidfile_close "struct pidfh *pfh"
44412fa8f1SPawel Jakub Dawidek.Ft int
45412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove "struct pidfh *pfh"
46f295618dSGuy Helmer.Ft int
47f295618dSGuy Helmer.Fn pidfile_fileno "struct pidfh *pfh"
48412fa8f1SPawel Jakub Dawidek.Sh DESCRIPTION
49412fa8f1SPawel Jakub DawidekThe
506b84cd58SRuslan Ermilov.Nm pidfile
516b84cd58SRuslan Ermilovfamily of functions allows daemons to handle PID files.
52412fa8f1SPawel Jakub DawidekIt uses
53cb7cd07aSDag-Erling Smørgrav.Xr flopen 3
546b84cd58SRuslan Ermilovto lock a pidfile and detect already running daemons.
55412fa8f1SPawel Jakub Dawidek.Pp
56412fa8f1SPawel Jakub DawidekThe
57412fa8f1SPawel Jakub Dawidek.Fn pidfile_open
586b84cd58SRuslan Ermilovfunction opens (or creates) a file specified by the
59412fa8f1SPawel Jakub Dawidek.Fa path
60cb7cd07aSDag-Erling Smørgravargument and locks it.
61e8cc80c0SPawel Jakub DawidekIf
62412fa8f1SPawel Jakub Dawidek.Fa pidptr
63e8cc80c0SPawel Jakub Dawidekargument is not
64e8cc80c0SPawel Jakub Dawidek.Dv NULL
65e8cc80c0SPawel Jakub Dawidekand file can not be locked, the function will use it to store a PID of an
66e8cc80c0SPawel Jakub Dawidekalready running daemon or
67e8cc80c0SPawel Jakub Dawidek.Li -1
68e8cc80c0SPawel Jakub Dawidekin case daemon did not write its PID yet.
696b84cd58SRuslan ErmilovThe function does not write process' PID into the file here, so it can be
706b84cd58SRuslan Ermilovused before
716b84cd58SRuslan Ermilov.Fn fork Ns ing
726b84cd58SRuslan Ermilovand exit with a proper error message when needed.
736b84cd58SRuslan ErmilovIf the
74412fa8f1SPawel Jakub Dawidek.Fa path
756b84cd58SRuslan Ermilovargument is
766b84cd58SRuslan Ermilov.Dv NULL ,
776b84cd58SRuslan Ermilov.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
78412fa8f1SPawel Jakub Dawidekfile will be used.
79719060e9SGuy HelmerThe
80719060e9SGuy Helmer.Fn pidfile_open
8150636e13SGuy Helmerfunction sets the O_CLOEXEC close-on-exec flag when opening the pidfile.
82412fa8f1SPawel Jakub Dawidek.Pp
83412fa8f1SPawel Jakub DawidekThe
84412fa8f1SPawel Jakub Dawidek.Fn pidfile_write
856b84cd58SRuslan Ermilovfunction writes process' PID into a previously opened file.
867f8d054fSPawel Jakub DawidekThe file is truncated before write, so calling the
877f8d054fSPawel Jakub Dawidek.Fn pidfile_write
887f8d054fSPawel Jakub Dawidekfunction multiple times is supported.
89412fa8f1SPawel Jakub Dawidek.Pp
90412fa8f1SPawel Jakub DawidekThe
91412fa8f1SPawel Jakub Dawidek.Fn pidfile_close
926b84cd58SRuslan Ermilovfunction closes a pidfile.
936b84cd58SRuslan ErmilovIt should be used after daemon
946b84cd58SRuslan Ermilov.Fn fork Ns s
956b84cd58SRuslan Ermilovto start a child process.
96412fa8f1SPawel Jakub Dawidek.Pp
97412fa8f1SPawel Jakub DawidekThe
98412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove
996b84cd58SRuslan Ermilovfunction closes and removes a pidfile.
100f295618dSGuy Helmer.Pp
101f295618dSGuy HelmerThe
102f295618dSGuy Helmer.Fn pidfile_fileno
103f295618dSGuy Helmerfunction returns the file descriptor for the open pidfile.
104412fa8f1SPawel Jakub Dawidek.Sh RETURN VALUES
105412fa8f1SPawel Jakub DawidekThe
106412fa8f1SPawel Jakub Dawidek.Fn pidfile_open
1076b84cd58SRuslan Ermilovfunction returns a valid pointer to a
1086b84cd58SRuslan Ermilov.Vt pidfh
1096b84cd58SRuslan Ermilovstructure on success, or
110412fa8f1SPawel Jakub Dawidek.Dv NULL
111412fa8f1SPawel Jakub Dawidekif an error occurs.
1126b84cd58SRuslan ErmilovIf an error occurs,
113412fa8f1SPawel Jakub Dawidek.Va errno
114412fa8f1SPawel Jakub Dawidekwill be set.
115a27c52a9SDag-Erling Smørgrav.Pp
116412fa8f1SPawel Jakub Dawidek.Rv -std pidfile_write pidfile_close pidfile_remove
117f295618dSGuy Helmer.Pp
118f295618dSGuy HelmerThe
119f295618dSGuy Helmer.Fn pidfile_fileno
120f295618dSGuy Helmerfunction returns the low-level file descriptor.
1214a25aa06SGuy HelmerIt returns
1224a25aa06SGuy Helmer.Li -1
1234a25aa06SGuy Helmerand sets
124f295618dSGuy Helmer.Va errno
125f295618dSGuy Helmerif a NULL
126f295618dSGuy Helmer.Vt pidfh
127f295618dSGuy Helmeris specified, or if the pidfile is no longer open.
128412fa8f1SPawel Jakub Dawidek.Sh EXAMPLES
1296b84cd58SRuslan ErmilovThe following example shows in which order these functions should be used.
130560c4fc1SPawel Jakub DawidekNote that it is safe to pass
131560c4fc1SPawel Jakub Dawidek.Dv NULL
132560c4fc1SPawel Jakub Dawidekto
133560c4fc1SPawel Jakub Dawidek.Fn pidfile_write ,
134f295618dSGuy Helmer.Fn pidfile_remove ,
135560c4fc1SPawel Jakub Dawidek.Fn pidfile_close
136f295618dSGuy Helmerand
137f295618dSGuy Helmer.Fn pidfile_fileno
138560c4fc1SPawel Jakub Dawidekfunctions.
139412fa8f1SPawel Jakub Dawidek.Bd -literal
140412fa8f1SPawel Jakub Dawidekstruct pidfh *pfh;
141412fa8f1SPawel Jakub Dawidekpid_t otherpid, childpid;
142412fa8f1SPawel Jakub Dawidek
1438b28aef2SPawel Jakub Dawidekpfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid);
144412fa8f1SPawel Jakub Dawidekif (pfh == NULL) {
145560c4fc1SPawel Jakub Dawidek	if (errno == EEXIST) {
146ef608a60SGiorgos Keramidas		errx(EXIT_FAILURE, "Daemon already running, pid: %jd.",
147ef608a60SGiorgos Keramidas		    (intmax_t)otherpid);
148560c4fc1SPawel Jakub Dawidek	}
149412fa8f1SPawel Jakub Dawidek	/* If we cannot create pidfile from other reasons, only warn. */
150412fa8f1SPawel Jakub Dawidek	warn("Cannot open or create pidfile");
151cc1ddd46SPawel Jakub Dawidek	/*
152cc1ddd46SPawel Jakub Dawidek	 * Even though pfh is NULL we can continue, as the other pidfile_*
153cc1ddd46SPawel Jakub Dawidek	 * function can handle such situation by doing nothing except setting
154cc1ddd46SPawel Jakub Dawidek	 * errno to EDOOFUS.
155cc1ddd46SPawel Jakub Dawidek	 */
156412fa8f1SPawel Jakub Dawidek}
157412fa8f1SPawel Jakub Dawidek
158412fa8f1SPawel Jakub Dawidekif (daemon(0, 0) == -1) {
159412fa8f1SPawel Jakub Dawidek	warn("Cannot daemonize");
160412fa8f1SPawel Jakub Dawidek	pidfile_remove(pfh);
161412fa8f1SPawel Jakub Dawidek	exit(EXIT_FAILURE);
162412fa8f1SPawel Jakub Dawidek}
163412fa8f1SPawel Jakub Dawidek
164412fa8f1SPawel Jakub Dawidekpidfile_write(pfh);
165412fa8f1SPawel Jakub Dawidek
166412fa8f1SPawel Jakub Dawidekfor (;;) {
167412fa8f1SPawel Jakub Dawidek	/* Do work. */
168412fa8f1SPawel Jakub Dawidek	childpid = fork();
169412fa8f1SPawel Jakub Dawidek	switch (childpid) {
170412fa8f1SPawel Jakub Dawidek	case -1:
171412fa8f1SPawel Jakub Dawidek		syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
172412fa8f1SPawel Jakub Dawidek		break;
173412fa8f1SPawel Jakub Dawidek	case 0:
174412fa8f1SPawel Jakub Dawidek		pidfile_close(pfh);
175412fa8f1SPawel Jakub Dawidek		/* Do child work. */
176412fa8f1SPawel Jakub Dawidek		break;
177412fa8f1SPawel Jakub Dawidek	default:
178ef608a60SGiorgos Keramidas		syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid);
179412fa8f1SPawel Jakub Dawidek		break;
180412fa8f1SPawel Jakub Dawidek	}
181412fa8f1SPawel Jakub Dawidek}
182412fa8f1SPawel Jakub Dawidek
183412fa8f1SPawel Jakub Dawidekpidfile_remove(pfh);
184412fa8f1SPawel Jakub Dawidekexit(EXIT_SUCCESS);
185412fa8f1SPawel Jakub Dawidek.Ed
186412fa8f1SPawel Jakub Dawidek.Sh ERRORS
187412fa8f1SPawel Jakub DawidekThe
188412fa8f1SPawel Jakub Dawidek.Fn pidfile_open
189412fa8f1SPawel Jakub Dawidekfunction will fail if:
190412fa8f1SPawel Jakub Dawidek.Bl -tag -width Er
191412fa8f1SPawel Jakub Dawidek.It Bq Er EEXIST
1926b84cd58SRuslan ErmilovSome process already holds the lock on the given pidfile, meaning that a
193412fa8f1SPawel Jakub Dawidekdaemon is already running.
194e8cc80c0SPawel Jakub DawidekIf
195e8cc80c0SPawel Jakub Dawidek.Fa pidptr
196e8cc80c0SPawel Jakub Dawidekargument is not
197e8cc80c0SPawel Jakub Dawidek.Dv NULL
198e8cc80c0SPawel Jakub Dawidekthe function will use it to store a PID of an already running daemon or
199e8cc80c0SPawel Jakub Dawidek.Li -1
200e8cc80c0SPawel Jakub Dawidekin case daemon did not write its PID yet.
201412fa8f1SPawel Jakub Dawidek.It Bq Er ENAMETOOLONG
202412fa8f1SPawel Jakub DawidekSpecified pidfile's name is too long.
203412fa8f1SPawel Jakub Dawidek.It Bq Er EINVAL
204412fa8f1SPawel Jakub DawidekSome process already holds the lock on the given pidfile, but PID read
205412fa8f1SPawel Jakub Dawidekfrom there is invalid.
206412fa8f1SPawel Jakub Dawidek.El
207412fa8f1SPawel Jakub Dawidek.Pp
208412fa8f1SPawel Jakub DawidekThe
209412fa8f1SPawel Jakub Dawidek.Fn pidfile_open
210412fa8f1SPawel Jakub Dawidekfunction may also fail and set
211412fa8f1SPawel Jakub Dawidek.Va errno
212412fa8f1SPawel Jakub Dawidekfor any errors specified for the
213412fa8f1SPawel Jakub Dawidek.Xr fstat 2 ,
214412fa8f1SPawel Jakub Dawidek.Xr open 2 ,
2156b84cd58SRuslan Ermilovand
216412fa8f1SPawel Jakub Dawidek.Xr read 2
2176b84cd58SRuslan Ermilovcalls.
218412fa8f1SPawel Jakub Dawidek.Pp
219412fa8f1SPawel Jakub DawidekThe
220412fa8f1SPawel Jakub Dawidek.Fn pidfile_write
221412fa8f1SPawel Jakub Dawidekfunction will fail if:
222412fa8f1SPawel Jakub Dawidek.Bl -tag -width Er
223412fa8f1SPawel Jakub Dawidek.It Bq Er EDOOFUS
2246b84cd58SRuslan ErmilovImproper function use.
225412fa8f1SPawel Jakub DawidekProbably called before
226412fa8f1SPawel Jakub Dawidek.Fn pidfile_open .
227412fa8f1SPawel Jakub Dawidek.El
228412fa8f1SPawel Jakub Dawidek.Pp
229412fa8f1SPawel Jakub DawidekThe
230412fa8f1SPawel Jakub Dawidek.Fn pidfile_write
231412fa8f1SPawel Jakub Dawidekfunction may also fail and set
232412fa8f1SPawel Jakub Dawidek.Va errno
233412fa8f1SPawel Jakub Dawidekfor any errors specified for the
234412fa8f1SPawel Jakub Dawidek.Xr fstat 2 ,
235412fa8f1SPawel Jakub Dawidek.Xr ftruncate 2 ,
2366b84cd58SRuslan Ermilovand
237412fa8f1SPawel Jakub Dawidek.Xr write 2
2386b84cd58SRuslan Ermilovcalls.
239412fa8f1SPawel Jakub Dawidek.Pp
240412fa8f1SPawel Jakub DawidekThe
241412fa8f1SPawel Jakub Dawidek.Fn pidfile_close
242412fa8f1SPawel Jakub Dawidekfunction may fail and set
243412fa8f1SPawel Jakub Dawidek.Va errno
244412fa8f1SPawel Jakub Dawidekfor any errors specified for the
2456b84cd58SRuslan Ermilov.Xr close 2
2466b84cd58SRuslan Ermilovand
247412fa8f1SPawel Jakub Dawidek.Xr fstat 2
2486b84cd58SRuslan Ermilovcalls.
249412fa8f1SPawel Jakub Dawidek.Pp
250412fa8f1SPawel Jakub DawidekThe
251412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove
252412fa8f1SPawel Jakub Dawidekfunction will fail if:
253412fa8f1SPawel Jakub Dawidek.Bl -tag -width Er
254412fa8f1SPawel Jakub Dawidek.It Bq Er EDOOFUS
2556b84cd58SRuslan ErmilovImproper function use.
256412fa8f1SPawel Jakub DawidekProbably called not from the process which made
257412fa8f1SPawel Jakub Dawidek.Fn pidfile_write .
258412fa8f1SPawel Jakub Dawidek.El
259412fa8f1SPawel Jakub Dawidek.Pp
260412fa8f1SPawel Jakub DawidekThe
261412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove
262412fa8f1SPawel Jakub Dawidekfunction may also fail and set
263412fa8f1SPawel Jakub Dawidek.Va errno
264412fa8f1SPawel Jakub Dawidekfor any errors specified for the
265412fa8f1SPawel Jakub Dawidek.Xr close 2 ,
266412fa8f1SPawel Jakub Dawidek.Xr fstat 2 ,
267412fa8f1SPawel Jakub Dawidek.Xr write 2 ,
2686b84cd58SRuslan Ermilovand
269412fa8f1SPawel Jakub Dawidek.Xr unlink 2
270cb7cd07aSDag-Erling Smørgravsystem calls and the
271cb7cd07aSDag-Erling Smørgrav.Xr flopen 3
272cb7cd07aSDag-Erling Smørgravlibrary function.
273f295618dSGuy Helmer.Pp
274f295618dSGuy HelmerThe
275f295618dSGuy Helmer.Fn pidfile_fileno
276f295618dSGuy Helmerfunction will fail if:
277f295618dSGuy Helmer.Bl -tag -width Er
278f295618dSGuy Helmer.It Bq Er EDOOFUS
279f295618dSGuy HelmerImproper function use.
280f295618dSGuy HelmerProbably called not from the process which used
281f295618dSGuy Helmer.Fn pidfile_open .
282f295618dSGuy Helmer.El
283412fa8f1SPawel Jakub Dawidek.Sh SEE ALSO
284412fa8f1SPawel Jakub Dawidek.Xr open 2 ,
285cb7cd07aSDag-Erling Smørgrav.Xr daemon 3 ,
286cb7cd07aSDag-Erling Smørgrav.Xr flopen 3
287*bc89b58dSGordon Bergling.Sh HISTORY
288*bc89b58dSGordon BerglingThe functions
289*bc89b58dSGordon Bergling.Fn pidfile_open ,
290*bc89b58dSGordon Bergling.Fn pidfile_write ,
291*bc89b58dSGordon Bergling.Fn pidfile_close
292*bc89b58dSGordon Berglingand
293*bc89b58dSGordon Bergling.Fn pidfile_remove
294*bc89b58dSGordon Berglingfirst appeared in
295*bc89b58dSGordon Bergling.Fx 5.5 .
296412fa8f1SPawel Jakub Dawidek.Sh AUTHORS
297412fa8f1SPawel Jakub Dawidek.An -nosplit
298412fa8f1SPawel Jakub DawidekThe
2996b84cd58SRuslan Ermilov.Nm pidfile
300412fa8f1SPawel Jakub Dawidekfunctionality is based on ideas from
3012b7af31cSBaptiste Daroussin.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
302412fa8f1SPawel Jakub Dawidek.Pp
303412fa8f1SPawel Jakub DawidekThe code and manual page was written by
3042b7af31cSBaptiste Daroussin.An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org .
305