mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-01-08 11:02:24 +01:00
Update pidfile module from FreeBSD
Use EINVAL instead of EDOOFUS. Add a missing synopsis for pidfile_fileno() in the man page. Move the definition of struct pidfh from libutil.h into pidfile.c following upstream change.
This commit is contained in:
parent
3d88c999b4
commit
facbddb652
@ -48,13 +48,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* for pidfile.c */
|
||||
struct pidfh {
|
||||
int pf_fd;
|
||||
char *pf_path;
|
||||
dev_t pf_dev;
|
||||
ino_t pf_ino;
|
||||
};
|
||||
struct pidfh;
|
||||
|
||||
__BEGIN_DECLS
|
||||
int humanize_number(char *buf, size_t len, int64_t bytes,
|
||||
@ -65,6 +59,7 @@ int flopen(const char *_path, int _flags, ...);
|
||||
int flopenat(int dirfd, const char *path, int flags, ...);
|
||||
|
||||
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
|
||||
int pidfile_fileno(const struct pidfh *pfh);
|
||||
int pidfile_write(struct pidfh *pfh);
|
||||
int pidfile_close(struct pidfh *pfh);
|
||||
int pidfile_remove(struct pidfh *pfh);
|
||||
|
@ -24,15 +24,16 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd October 20, 2008
|
||||
.Dd February 8, 2012
|
||||
.Dt PIDFILE 3bsd
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm pidfile_open ,
|
||||
.Nm pidfile_write ,
|
||||
.Nm pidfile_close ,
|
||||
.Nm pidfile_remove
|
||||
.Nd library for PID files handling
|
||||
.Nm pidfile_remove ,
|
||||
.Nm pidfile_fileno
|
||||
.Nd "library for PID files handling"
|
||||
.Sh LIBRARY
|
||||
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
|
||||
.Lb libbsd
|
||||
@ -49,6 +50,8 @@ for include usage.)
|
||||
.Fn pidfile_close "struct pidfh *pfh"
|
||||
.Ft int
|
||||
.Fn pidfile_remove "struct pidfh *pfh"
|
||||
.Ft int
|
||||
.Fn pidfile_fileno "struct pidfh *pfh"
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm pidfile
|
||||
@ -62,11 +65,14 @@ The
|
||||
function opens (or creates) a file specified by the
|
||||
.Fa path
|
||||
argument and locks it.
|
||||
If a file can not be locked, a PID of an already running daemon is returned in
|
||||
the
|
||||
If
|
||||
.Fa pidptr
|
||||
argument (if it is not
|
||||
.Dv NULL ) .
|
||||
argument is not
|
||||
.Dv NULL
|
||||
and file can not be locked, the function will use it to store a PID of an
|
||||
already running daemon or
|
||||
.Li -1
|
||||
in case daemon did not write its PID yet.
|
||||
The function does not write process' PID into the file here, so it can be
|
||||
used before
|
||||
.Fn fork Ns ing
|
||||
@ -77,10 +83,16 @@ argument is
|
||||
.Dv NULL ,
|
||||
.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
|
||||
file will be used.
|
||||
The
|
||||
.Fn pidfile_open
|
||||
function sets the O_CLOEXEC close-on-exec flag when opening the pidfile.
|
||||
.Pp
|
||||
The
|
||||
.Fn pidfile_write
|
||||
function writes process' PID into a previously opened file.
|
||||
The file is truncated before write, so calling the
|
||||
.Fn pidfile_write
|
||||
function multiple times is supported.
|
||||
.Pp
|
||||
The
|
||||
.Fn pidfile_close
|
||||
@ -92,6 +104,10 @@ to start a child process.
|
||||
The
|
||||
.Fn pidfile_remove
|
||||
function closes and removes a pidfile.
|
||||
.Pp
|
||||
The
|
||||
.Fn pidfile_fileno
|
||||
function returns the file descriptor for the open pidfile.
|
||||
.Sh RETURN VALUES
|
||||
The
|
||||
.Fn pidfile_open
|
||||
@ -105,15 +121,27 @@ If an error occurs,
|
||||
will be set.
|
||||
.Pp
|
||||
.Rv -std pidfile_write pidfile_close pidfile_remove
|
||||
.Pp
|
||||
The
|
||||
.Fn pidfile_fileno
|
||||
function returns the low-level file descriptor.
|
||||
It returns
|
||||
.Li -1
|
||||
and sets
|
||||
.Va errno
|
||||
if a NULL
|
||||
.Vt pidfh
|
||||
is specified, or if the pidfile is no longer open.
|
||||
.Sh EXAMPLES
|
||||
The following example shows in which order these functions should be used.
|
||||
Note that it is safe to pass
|
||||
.Dv NULL
|
||||
to
|
||||
.Fn pidfile_write ,
|
||||
.Fn pidfile_remove
|
||||
and
|
||||
.Fn pidfile_remove ,
|
||||
.Fn pidfile_close
|
||||
and
|
||||
.Fn pidfile_fileno
|
||||
functions.
|
||||
.Bd -literal
|
||||
struct pidfh *pfh;
|
||||
@ -127,6 +155,11 @@ if (pfh == NULL) {
|
||||
}
|
||||
/* 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) {
|
||||
@ -165,16 +198,18 @@ function will fail if:
|
||||
.It Bq Er EEXIST
|
||||
Some process already holds the lock on the given pidfile, meaning that a
|
||||
daemon is already running.
|
||||
If
|
||||
.Fa pidptr
|
||||
argument is not
|
||||
.Dv NULL
|
||||
the function will use it to store a PID of an already running daemon or
|
||||
.Li -1
|
||||
in case daemon did not write its PID yet.
|
||||
.It Bq Er ENAMETOOLONG
|
||||
Specified pidfile's name is too long.
|
||||
.It Bq Er EINVAL
|
||||
Some process already holds the lock on the given pidfile, but PID read
|
||||
from there is invalid.
|
||||
.It Bq Er EAGAIN
|
||||
Some process already holds the lock on the given pidfile, but the file
|
||||
is truncated.
|
||||
Most likely, the existing daemon is writing new PID into
|
||||
the file.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
@ -242,6 +277,16 @@ and
|
||||
system calls and the
|
||||
.Xr flopen 3bsd
|
||||
library function.
|
||||
.Pp
|
||||
The
|
||||
.Fn pidfile_fileno
|
||||
function will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EINVAL
|
||||
Improper function use.
|
||||
Probably called not from the process which used
|
||||
.Fn pidfile_open .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr open 2 ,
|
||||
.Xr daemon 3 ,
|
||||
@ -251,7 +296,7 @@ library function.
|
||||
The
|
||||
.Nm pidfile
|
||||
functionality is based on ideas from
|
||||
.An John-Mark Gurney Aq jmg@FreeBSD.org .
|
||||
.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
|
||||
.Pp
|
||||
The code and manual page was written by
|
||||
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org .
|
||||
.An Pawel Jakub Dawidek Aq Mt pjd@FreeBSD.org .
|
||||
|
@ -142,4 +142,6 @@ LIBBSD_0.8 {
|
||||
|
||||
LIBBSD_0.9 {
|
||||
flopenat;
|
||||
|
||||
pidfile_fileno;
|
||||
} LIBBSD_0.8;
|
||||
|
@ -29,20 +29,27 @@
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <libutil.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct pidfh {
|
||||
int pf_fd;
|
||||
char *pf_path;
|
||||
dev_t pf_dev;
|
||||
ino_t pf_ino;
|
||||
};
|
||||
|
||||
static int _pidfile_remove(struct pidfh *pfh, int freeit);
|
||||
|
||||
static int
|
||||
pidfile_verify(struct pidfh *pfh)
|
||||
pidfile_verify(const struct pidfh *pfh)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
@ -114,25 +121,33 @@ pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
|
||||
fd = flopen(pfh->pf_path,
|
||||
O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
|
||||
if (fd == -1) {
|
||||
count = 0;
|
||||
rqtp.tv_sec = 0;
|
||||
rqtp.tv_nsec = 5000000;
|
||||
if (errno == EWOULDBLOCK && pidptr != NULL) {
|
||||
again:
|
||||
errno = pidfile_read(pfh->pf_path, pidptr);
|
||||
if (errno == 0)
|
||||
if (errno == EWOULDBLOCK) {
|
||||
if (pidptr == NULL) {
|
||||
errno = EEXIST;
|
||||
else if (errno == EAGAIN) {
|
||||
if (++count <= 3) {
|
||||
} else {
|
||||
count = 20;
|
||||
rqtp.tv_sec = 0;
|
||||
rqtp.tv_nsec = 5000000;
|
||||
for (;;) {
|
||||
errno = pidfile_read(pfh->pf_path,
|
||||
pidptr);
|
||||
if (errno != EAGAIN || --count == 0)
|
||||
break;
|
||||
nanosleep(&rqtp, 0);
|
||||
goto again;
|
||||
}
|
||||
if (errno == EAGAIN)
|
||||
*pidptr = -1;
|
||||
if (errno == 0 || errno == EAGAIN)
|
||||
errno = EEXIST;
|
||||
}
|
||||
}
|
||||
error = errno;
|
||||
free(pfh->pf_path);
|
||||
free(pfh);
|
||||
errno = error;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remember file information, so in pidfile_write() we are sure we write
|
||||
* to the proper descriptor.
|
||||
@ -251,3 +266,14 @@ pidfile_remove(struct pidfh *pfh)
|
||||
|
||||
return (_pidfile_remove(pfh, 1));
|
||||
}
|
||||
|
||||
int
|
||||
pidfile_fileno(const struct pidfh *pfh)
|
||||
{
|
||||
|
||||
if (pfh == NULL || pfh->pf_fd == -1) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
return (pfh->pf_fd);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user