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.\" 25412fa8f1SPawel Jakub Dawidek.\" $FreeBSD$ 26412fa8f1SPawel Jakub Dawidek.\" 27*bc89b58dSGordon Bergling.Dd May 10, 2020 28412fa8f1SPawel Jakub Dawidek.Dt PIDFILE 3 29412fa8f1SPawel Jakub Dawidek.Os 30412fa8f1SPawel Jakub Dawidek.Sh NAME 31412fa8f1SPawel Jakub Dawidek.Nm pidfile_open , 32412fa8f1SPawel Jakub Dawidek.Nm pidfile_write , 33412fa8f1SPawel Jakub Dawidek.Nm pidfile_close , 34412fa8f1SPawel Jakub Dawidek.Nm pidfile_remove 356b84cd58SRuslan Ermilov.Nd "library for PID files handling" 36412fa8f1SPawel Jakub Dawidek.Sh LIBRARY 37412fa8f1SPawel Jakub Dawidek.Lb libutil 38412fa8f1SPawel Jakub Dawidek.Sh SYNOPSIS 39412fa8f1SPawel Jakub Dawidek.In libutil.h 406b84cd58SRuslan Ermilov.Ft "struct pidfh *" 41412fa8f1SPawel Jakub Dawidek.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr" 42412fa8f1SPawel Jakub Dawidek.Ft int 43412fa8f1SPawel Jakub Dawidek.Fn pidfile_write "struct pidfh *pfh" 44412fa8f1SPawel Jakub Dawidek.Ft int 45412fa8f1SPawel Jakub Dawidek.Fn pidfile_close "struct pidfh *pfh" 46412fa8f1SPawel Jakub Dawidek.Ft int 47412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove "struct pidfh *pfh" 48f295618dSGuy Helmer.Ft int 49f295618dSGuy Helmer.Fn pidfile_fileno "struct pidfh *pfh" 50412fa8f1SPawel Jakub Dawidek.Sh DESCRIPTION 51412fa8f1SPawel Jakub DawidekThe 526b84cd58SRuslan Ermilov.Nm pidfile 536b84cd58SRuslan Ermilovfamily of functions allows daemons to handle PID files. 54412fa8f1SPawel Jakub DawidekIt uses 55cb7cd07aSDag-Erling Smørgrav.Xr flopen 3 566b84cd58SRuslan Ermilovto lock a pidfile and detect already running daemons. 57412fa8f1SPawel Jakub Dawidek.Pp 58412fa8f1SPawel Jakub DawidekThe 59412fa8f1SPawel Jakub Dawidek.Fn pidfile_open 606b84cd58SRuslan Ermilovfunction opens (or creates) a file specified by the 61412fa8f1SPawel Jakub Dawidek.Fa path 62cb7cd07aSDag-Erling Smørgravargument and locks it. 63e8cc80c0SPawel Jakub DawidekIf 64412fa8f1SPawel Jakub Dawidek.Fa pidptr 65e8cc80c0SPawel Jakub Dawidekargument is not 66e8cc80c0SPawel Jakub Dawidek.Dv NULL 67e8cc80c0SPawel Jakub Dawidekand file can not be locked, the function will use it to store a PID of an 68e8cc80c0SPawel Jakub Dawidekalready running daemon or 69e8cc80c0SPawel Jakub Dawidek.Li -1 70e8cc80c0SPawel Jakub Dawidekin case daemon did not write its PID yet. 716b84cd58SRuslan ErmilovThe function does not write process' PID into the file here, so it can be 726b84cd58SRuslan Ermilovused before 736b84cd58SRuslan Ermilov.Fn fork Ns ing 746b84cd58SRuslan Ermilovand exit with a proper error message when needed. 756b84cd58SRuslan ErmilovIf the 76412fa8f1SPawel Jakub Dawidek.Fa path 776b84cd58SRuslan Ermilovargument is 786b84cd58SRuslan Ermilov.Dv NULL , 796b84cd58SRuslan Ermilov.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid 80412fa8f1SPawel Jakub Dawidekfile will be used. 81719060e9SGuy HelmerThe 82719060e9SGuy Helmer.Fn pidfile_open 8350636e13SGuy Helmerfunction sets the O_CLOEXEC close-on-exec flag when opening the pidfile. 84412fa8f1SPawel Jakub Dawidek.Pp 85412fa8f1SPawel Jakub DawidekThe 86412fa8f1SPawel Jakub Dawidek.Fn pidfile_write 876b84cd58SRuslan Ermilovfunction writes process' PID into a previously opened file. 887f8d054fSPawel Jakub DawidekThe file is truncated before write, so calling the 897f8d054fSPawel Jakub Dawidek.Fn pidfile_write 907f8d054fSPawel Jakub Dawidekfunction multiple times is supported. 91412fa8f1SPawel Jakub Dawidek.Pp 92412fa8f1SPawel Jakub DawidekThe 93412fa8f1SPawel Jakub Dawidek.Fn pidfile_close 946b84cd58SRuslan Ermilovfunction closes a pidfile. 956b84cd58SRuslan ErmilovIt should be used after daemon 966b84cd58SRuslan Ermilov.Fn fork Ns s 976b84cd58SRuslan Ermilovto start a child process. 98412fa8f1SPawel Jakub Dawidek.Pp 99412fa8f1SPawel Jakub DawidekThe 100412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove 1016b84cd58SRuslan Ermilovfunction closes and removes a pidfile. 102f295618dSGuy Helmer.Pp 103f295618dSGuy HelmerThe 104f295618dSGuy Helmer.Fn pidfile_fileno 105f295618dSGuy Helmerfunction returns the file descriptor for the open pidfile. 106412fa8f1SPawel Jakub Dawidek.Sh RETURN VALUES 107412fa8f1SPawel Jakub DawidekThe 108412fa8f1SPawel Jakub Dawidek.Fn pidfile_open 1096b84cd58SRuslan Ermilovfunction returns a valid pointer to a 1106b84cd58SRuslan Ermilov.Vt pidfh 1116b84cd58SRuslan Ermilovstructure on success, or 112412fa8f1SPawel Jakub Dawidek.Dv NULL 113412fa8f1SPawel Jakub Dawidekif an error occurs. 1146b84cd58SRuslan ErmilovIf an error occurs, 115412fa8f1SPawel Jakub Dawidek.Va errno 116412fa8f1SPawel Jakub Dawidekwill be set. 117a27c52a9SDag-Erling Smørgrav.Pp 118412fa8f1SPawel Jakub Dawidek.Rv -std pidfile_write pidfile_close pidfile_remove 119f295618dSGuy Helmer.Pp 120f295618dSGuy HelmerThe 121f295618dSGuy Helmer.Fn pidfile_fileno 122f295618dSGuy Helmerfunction returns the low-level file descriptor. 1234a25aa06SGuy HelmerIt returns 1244a25aa06SGuy Helmer.Li -1 1254a25aa06SGuy Helmerand sets 126f295618dSGuy Helmer.Va errno 127f295618dSGuy Helmerif a NULL 128f295618dSGuy Helmer.Vt pidfh 129f295618dSGuy Helmeris specified, or if the pidfile is no longer open. 130412fa8f1SPawel Jakub Dawidek.Sh EXAMPLES 1316b84cd58SRuslan ErmilovThe following example shows in which order these functions should be used. 132560c4fc1SPawel Jakub DawidekNote that it is safe to pass 133560c4fc1SPawel Jakub Dawidek.Dv NULL 134560c4fc1SPawel Jakub Dawidekto 135560c4fc1SPawel Jakub Dawidek.Fn pidfile_write , 136f295618dSGuy Helmer.Fn pidfile_remove , 137560c4fc1SPawel Jakub Dawidek.Fn pidfile_close 138f295618dSGuy Helmerand 139f295618dSGuy Helmer.Fn pidfile_fileno 140560c4fc1SPawel Jakub Dawidekfunctions. 141412fa8f1SPawel Jakub Dawidek.Bd -literal 142412fa8f1SPawel Jakub Dawidekstruct pidfh *pfh; 143412fa8f1SPawel Jakub Dawidekpid_t otherpid, childpid; 144412fa8f1SPawel Jakub Dawidek 1458b28aef2SPawel Jakub Dawidekpfh = pidfile_open("/var/run/daemon.pid", 0600, &otherpid); 146412fa8f1SPawel Jakub Dawidekif (pfh == NULL) { 147560c4fc1SPawel Jakub Dawidek if (errno == EEXIST) { 148ef608a60SGiorgos Keramidas errx(EXIT_FAILURE, "Daemon already running, pid: %jd.", 149ef608a60SGiorgos Keramidas (intmax_t)otherpid); 150560c4fc1SPawel Jakub Dawidek } 151412fa8f1SPawel Jakub Dawidek /* If we cannot create pidfile from other reasons, only warn. */ 152412fa8f1SPawel Jakub Dawidek warn("Cannot open or create pidfile"); 153cc1ddd46SPawel Jakub Dawidek /* 154cc1ddd46SPawel Jakub Dawidek * Even though pfh is NULL we can continue, as the other pidfile_* 155cc1ddd46SPawel Jakub Dawidek * function can handle such situation by doing nothing except setting 156cc1ddd46SPawel Jakub Dawidek * errno to EDOOFUS. 157cc1ddd46SPawel Jakub Dawidek */ 158412fa8f1SPawel Jakub Dawidek} 159412fa8f1SPawel Jakub Dawidek 160412fa8f1SPawel Jakub Dawidekif (daemon(0, 0) == -1) { 161412fa8f1SPawel Jakub Dawidek warn("Cannot daemonize"); 162412fa8f1SPawel Jakub Dawidek pidfile_remove(pfh); 163412fa8f1SPawel Jakub Dawidek exit(EXIT_FAILURE); 164412fa8f1SPawel Jakub Dawidek} 165412fa8f1SPawel Jakub Dawidek 166412fa8f1SPawel Jakub Dawidekpidfile_write(pfh); 167412fa8f1SPawel Jakub Dawidek 168412fa8f1SPawel Jakub Dawidekfor (;;) { 169412fa8f1SPawel Jakub Dawidek /* Do work. */ 170412fa8f1SPawel Jakub Dawidek childpid = fork(); 171412fa8f1SPawel Jakub Dawidek switch (childpid) { 172412fa8f1SPawel Jakub Dawidek case -1: 173412fa8f1SPawel Jakub Dawidek syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno)); 174412fa8f1SPawel Jakub Dawidek break; 175412fa8f1SPawel Jakub Dawidek case 0: 176412fa8f1SPawel Jakub Dawidek pidfile_close(pfh); 177412fa8f1SPawel Jakub Dawidek /* Do child work. */ 178412fa8f1SPawel Jakub Dawidek break; 179412fa8f1SPawel Jakub Dawidek default: 180ef608a60SGiorgos Keramidas syslog(LOG_INFO, "Child %jd started.", (intmax_t)childpid); 181412fa8f1SPawel Jakub Dawidek break; 182412fa8f1SPawel Jakub Dawidek } 183412fa8f1SPawel Jakub Dawidek} 184412fa8f1SPawel Jakub Dawidek 185412fa8f1SPawel Jakub Dawidekpidfile_remove(pfh); 186412fa8f1SPawel Jakub Dawidekexit(EXIT_SUCCESS); 187412fa8f1SPawel Jakub Dawidek.Ed 188412fa8f1SPawel Jakub Dawidek.Sh ERRORS 189412fa8f1SPawel Jakub DawidekThe 190412fa8f1SPawel Jakub Dawidek.Fn pidfile_open 191412fa8f1SPawel Jakub Dawidekfunction will fail if: 192412fa8f1SPawel Jakub Dawidek.Bl -tag -width Er 193412fa8f1SPawel Jakub Dawidek.It Bq Er EEXIST 1946b84cd58SRuslan ErmilovSome process already holds the lock on the given pidfile, meaning that a 195412fa8f1SPawel Jakub Dawidekdaemon is already running. 196e8cc80c0SPawel Jakub DawidekIf 197e8cc80c0SPawel Jakub Dawidek.Fa pidptr 198e8cc80c0SPawel Jakub Dawidekargument is not 199e8cc80c0SPawel Jakub Dawidek.Dv NULL 200e8cc80c0SPawel Jakub Dawidekthe function will use it to store a PID of an already running daemon or 201e8cc80c0SPawel Jakub Dawidek.Li -1 202e8cc80c0SPawel Jakub Dawidekin case daemon did not write its PID yet. 203412fa8f1SPawel Jakub Dawidek.It Bq Er ENAMETOOLONG 204412fa8f1SPawel Jakub DawidekSpecified pidfile's name is too long. 205412fa8f1SPawel Jakub Dawidek.It Bq Er EINVAL 206412fa8f1SPawel Jakub DawidekSome process already holds the lock on the given pidfile, but PID read 207412fa8f1SPawel Jakub Dawidekfrom there is invalid. 208412fa8f1SPawel Jakub Dawidek.El 209412fa8f1SPawel Jakub Dawidek.Pp 210412fa8f1SPawel Jakub DawidekThe 211412fa8f1SPawel Jakub Dawidek.Fn pidfile_open 212412fa8f1SPawel Jakub Dawidekfunction may also fail and set 213412fa8f1SPawel Jakub Dawidek.Va errno 214412fa8f1SPawel Jakub Dawidekfor any errors specified for the 215412fa8f1SPawel Jakub Dawidek.Xr fstat 2 , 216412fa8f1SPawel Jakub Dawidek.Xr open 2 , 2176b84cd58SRuslan Ermilovand 218412fa8f1SPawel Jakub Dawidek.Xr read 2 2196b84cd58SRuslan Ermilovcalls. 220412fa8f1SPawel Jakub Dawidek.Pp 221412fa8f1SPawel Jakub DawidekThe 222412fa8f1SPawel Jakub Dawidek.Fn pidfile_write 223412fa8f1SPawel Jakub Dawidekfunction will fail if: 224412fa8f1SPawel Jakub Dawidek.Bl -tag -width Er 225412fa8f1SPawel Jakub Dawidek.It Bq Er EDOOFUS 2266b84cd58SRuslan ErmilovImproper function use. 227412fa8f1SPawel Jakub DawidekProbably called before 228412fa8f1SPawel Jakub Dawidek.Fn pidfile_open . 229412fa8f1SPawel Jakub Dawidek.El 230412fa8f1SPawel Jakub Dawidek.Pp 231412fa8f1SPawel Jakub DawidekThe 232412fa8f1SPawel Jakub Dawidek.Fn pidfile_write 233412fa8f1SPawel Jakub Dawidekfunction may also fail and set 234412fa8f1SPawel Jakub Dawidek.Va errno 235412fa8f1SPawel Jakub Dawidekfor any errors specified for the 236412fa8f1SPawel Jakub Dawidek.Xr fstat 2 , 237412fa8f1SPawel Jakub Dawidek.Xr ftruncate 2 , 2386b84cd58SRuslan Ermilovand 239412fa8f1SPawel Jakub Dawidek.Xr write 2 2406b84cd58SRuslan Ermilovcalls. 241412fa8f1SPawel Jakub Dawidek.Pp 242412fa8f1SPawel Jakub DawidekThe 243412fa8f1SPawel Jakub Dawidek.Fn pidfile_close 244412fa8f1SPawel Jakub Dawidekfunction may fail and set 245412fa8f1SPawel Jakub Dawidek.Va errno 246412fa8f1SPawel Jakub Dawidekfor any errors specified for the 2476b84cd58SRuslan Ermilov.Xr close 2 2486b84cd58SRuslan Ermilovand 249412fa8f1SPawel Jakub Dawidek.Xr fstat 2 2506b84cd58SRuslan Ermilovcalls. 251412fa8f1SPawel Jakub Dawidek.Pp 252412fa8f1SPawel Jakub DawidekThe 253412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove 254412fa8f1SPawel Jakub Dawidekfunction will fail if: 255412fa8f1SPawel Jakub Dawidek.Bl -tag -width Er 256412fa8f1SPawel Jakub Dawidek.It Bq Er EDOOFUS 2576b84cd58SRuslan ErmilovImproper function use. 258412fa8f1SPawel Jakub DawidekProbably called not from the process which made 259412fa8f1SPawel Jakub Dawidek.Fn pidfile_write . 260412fa8f1SPawel Jakub Dawidek.El 261412fa8f1SPawel Jakub Dawidek.Pp 262412fa8f1SPawel Jakub DawidekThe 263412fa8f1SPawel Jakub Dawidek.Fn pidfile_remove 264412fa8f1SPawel Jakub Dawidekfunction may also fail and set 265412fa8f1SPawel Jakub Dawidek.Va errno 266412fa8f1SPawel Jakub Dawidekfor any errors specified for the 267412fa8f1SPawel Jakub Dawidek.Xr close 2 , 268412fa8f1SPawel Jakub Dawidek.Xr fstat 2 , 269412fa8f1SPawel Jakub Dawidek.Xr write 2 , 2706b84cd58SRuslan Ermilovand 271412fa8f1SPawel Jakub Dawidek.Xr unlink 2 272cb7cd07aSDag-Erling Smørgravsystem calls and the 273cb7cd07aSDag-Erling Smørgrav.Xr flopen 3 274cb7cd07aSDag-Erling Smørgravlibrary function. 275f295618dSGuy Helmer.Pp 276f295618dSGuy HelmerThe 277f295618dSGuy Helmer.Fn pidfile_fileno 278f295618dSGuy Helmerfunction will fail if: 279f295618dSGuy Helmer.Bl -tag -width Er 280f295618dSGuy Helmer.It Bq Er EDOOFUS 281f295618dSGuy HelmerImproper function use. 282f295618dSGuy HelmerProbably called not from the process which used 283f295618dSGuy Helmer.Fn pidfile_open . 284f295618dSGuy Helmer.El 285412fa8f1SPawel Jakub Dawidek.Sh SEE ALSO 286412fa8f1SPawel Jakub Dawidek.Xr open 2 , 287cb7cd07aSDag-Erling Smørgrav.Xr daemon 3 , 288cb7cd07aSDag-Erling Smørgrav.Xr flopen 3 289*bc89b58dSGordon Bergling.Sh HISTORY 290*bc89b58dSGordon BerglingThe functions 291*bc89b58dSGordon Bergling.Fn pidfile_open , 292*bc89b58dSGordon Bergling.Fn pidfile_write , 293*bc89b58dSGordon Bergling.Fn pidfile_close 294*bc89b58dSGordon Berglingand 295*bc89b58dSGordon Bergling.Fn pidfile_remove 296*bc89b58dSGordon Berglingfirst appeared in 297*bc89b58dSGordon Bergling.Fx 5.5 . 298412fa8f1SPawel Jakub Dawidek.Sh AUTHORS 299412fa8f1SPawel Jakub Dawidek.An -nosplit 300412fa8f1SPawel Jakub DawidekThe 3016b84cd58SRuslan Ermilov.Nm pidfile 302412fa8f1SPawel Jakub Dawidekfunctionality is based on ideas from 3032b7af31cSBaptiste Daroussin.An John-Mark Gurney Aq Mt jmg@FreeBSD.org . 304412fa8f1SPawel Jakub Dawidek.Pp 305412fa8f1SPawel Jakub DawidekThe code and manual page was written by 3062b7af31cSBaptiste Daroussin.An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org . 307