mirror of
https://gitlab.freedesktop.org/libbsd/libbsd.git
synced 2025-01-09 11:17:37 +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 <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
/* for pidfile.c */
|
struct pidfh;
|
||||||
struct pidfh {
|
|
||||||
int pf_fd;
|
|
||||||
char *pf_path;
|
|
||||||
dev_t pf_dev;
|
|
||||||
ino_t pf_ino;
|
|
||||||
};
|
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
int humanize_number(char *buf, size_t len, int64_t bytes,
|
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, ...);
|
int flopenat(int dirfd, const char *path, int flags, ...);
|
||||||
|
|
||||||
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
|
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_write(struct pidfh *pfh);
|
||||||
int pidfile_close(struct pidfh *pfh);
|
int pidfile_close(struct pidfh *pfh);
|
||||||
int pidfile_remove(struct pidfh *pfh);
|
int pidfile_remove(struct pidfh *pfh);
|
||||||
|
@ -24,15 +24,16 @@
|
|||||||
.\"
|
.\"
|
||||||
.\" $FreeBSD$
|
.\" $FreeBSD$
|
||||||
.\"
|
.\"
|
||||||
.Dd October 20, 2008
|
.Dd February 8, 2012
|
||||||
.Dt PIDFILE 3bsd
|
.Dt PIDFILE 3bsd
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
.Nm pidfile_open ,
|
.Nm pidfile_open ,
|
||||||
.Nm pidfile_write ,
|
.Nm pidfile_write ,
|
||||||
.Nm pidfile_close ,
|
.Nm pidfile_close ,
|
||||||
.Nm pidfile_remove
|
.Nm pidfile_remove ,
|
||||||
.Nd library for PID files handling
|
.Nm pidfile_fileno
|
||||||
|
.Nd "library for PID files handling"
|
||||||
.Sh LIBRARY
|
.Sh LIBRARY
|
||||||
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
|
.ds str-Lb-libbsd Utility functions from BSD systems (libbsd, \-lbsd)
|
||||||
.Lb libbsd
|
.Lb libbsd
|
||||||
@ -49,6 +50,8 @@ for include usage.)
|
|||||||
.Fn pidfile_close "struct pidfh *pfh"
|
.Fn pidfile_close "struct pidfh *pfh"
|
||||||
.Ft int
|
.Ft int
|
||||||
.Fn pidfile_remove "struct pidfh *pfh"
|
.Fn pidfile_remove "struct pidfh *pfh"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_fileno "struct pidfh *pfh"
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
The
|
The
|
||||||
.Nm pidfile
|
.Nm pidfile
|
||||||
@ -62,11 +65,14 @@ The
|
|||||||
function opens (or creates) a file specified by the
|
function opens (or creates) a file specified by the
|
||||||
.Fa path
|
.Fa path
|
||||||
argument and locks it.
|
argument and locks it.
|
||||||
If a file can not be locked, a PID of an already running daemon is returned in
|
If
|
||||||
the
|
|
||||||
.Fa pidptr
|
.Fa pidptr
|
||||||
argument (if it is not
|
argument is not
|
||||||
.Dv NULL ) .
|
.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
|
The function does not write process' PID into the file here, so it can be
|
||||||
used before
|
used before
|
||||||
.Fn fork Ns ing
|
.Fn fork Ns ing
|
||||||
@ -77,10 +83,16 @@ argument is
|
|||||||
.Dv NULL ,
|
.Dv NULL ,
|
||||||
.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
|
.Pa /var/run/ Ns Ao Va progname Ac Ns Pa .pid
|
||||||
file will be used.
|
file will be used.
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function sets the O_CLOEXEC close-on-exec flag when opening the pidfile.
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn pidfile_write
|
.Fn pidfile_write
|
||||||
function writes process' PID into a previously opened file.
|
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
|
.Pp
|
||||||
The
|
The
|
||||||
.Fn pidfile_close
|
.Fn pidfile_close
|
||||||
@ -92,6 +104,10 @@ to start a child process.
|
|||||||
The
|
The
|
||||||
.Fn pidfile_remove
|
.Fn pidfile_remove
|
||||||
function closes and removes a pidfile.
|
function closes and removes a pidfile.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_fileno
|
||||||
|
function returns the file descriptor for the open pidfile.
|
||||||
.Sh RETURN VALUES
|
.Sh RETURN VALUES
|
||||||
The
|
The
|
||||||
.Fn pidfile_open
|
.Fn pidfile_open
|
||||||
@ -105,15 +121,27 @@ If an error occurs,
|
|||||||
will be set.
|
will be set.
|
||||||
.Pp
|
.Pp
|
||||||
.Rv -std pidfile_write pidfile_close pidfile_remove
|
.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
|
.Sh EXAMPLES
|
||||||
The following example shows in which order these functions should be used.
|
The following example shows in which order these functions should be used.
|
||||||
Note that it is safe to pass
|
Note that it is safe to pass
|
||||||
.Dv NULL
|
.Dv NULL
|
||||||
to
|
to
|
||||||
.Fn pidfile_write ,
|
.Fn pidfile_write ,
|
||||||
.Fn pidfile_remove
|
.Fn pidfile_remove ,
|
||||||
and
|
|
||||||
.Fn pidfile_close
|
.Fn pidfile_close
|
||||||
|
and
|
||||||
|
.Fn pidfile_fileno
|
||||||
functions.
|
functions.
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
struct pidfh *pfh;
|
struct pidfh *pfh;
|
||||||
@ -127,6 +155,11 @@ if (pfh == NULL) {
|
|||||||
}
|
}
|
||||||
/* If we cannot create pidfile from other reasons, only warn. */
|
/* If we cannot create pidfile from other reasons, only warn. */
|
||||||
warn("Cannot open or create pidfile");
|
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) {
|
if (daemon(0, 0) == \-1) {
|
||||||
@ -165,16 +198,18 @@ function will fail if:
|
|||||||
.It Bq Er EEXIST
|
.It Bq Er EEXIST
|
||||||
Some process already holds the lock on the given pidfile, meaning that a
|
Some process already holds the lock on the given pidfile, meaning that a
|
||||||
daemon is already running.
|
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
|
.It Bq Er ENAMETOOLONG
|
||||||
Specified pidfile's name is too long.
|
Specified pidfile's name is too long.
|
||||||
.It Bq Er EINVAL
|
.It Bq Er EINVAL
|
||||||
Some process already holds the lock on the given pidfile, but PID read
|
Some process already holds the lock on the given pidfile, but PID read
|
||||||
from there is invalid.
|
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
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
@ -242,6 +277,16 @@ and
|
|||||||
system calls and the
|
system calls and the
|
||||||
.Xr flopen 3bsd
|
.Xr flopen 3bsd
|
||||||
library function.
|
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
|
.Sh SEE ALSO
|
||||||
.Xr open 2 ,
|
.Xr open 2 ,
|
||||||
.Xr daemon 3 ,
|
.Xr daemon 3 ,
|
||||||
@ -251,7 +296,7 @@ library function.
|
|||||||
The
|
The
|
||||||
.Nm pidfile
|
.Nm pidfile
|
||||||
functionality is based on ideas from
|
functionality is based on ideas from
|
||||||
.An John-Mark Gurney Aq jmg@FreeBSD.org .
|
.An John-Mark Gurney Aq Mt jmg@FreeBSD.org .
|
||||||
.Pp
|
.Pp
|
||||||
The code and manual page was written by
|
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 {
|
LIBBSD_0.9 {
|
||||||
flopenat;
|
flopenat;
|
||||||
|
|
||||||
|
pidfile_fileno;
|
||||||
} LIBBSD_0.8;
|
} LIBBSD_0.8;
|
||||||
|
@ -29,20 +29,27 @@
|
|||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
#include <sys/stat.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 <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <libutil.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_remove(struct pidfh *pfh, int freeit);
|
||||||
|
|
||||||
static int
|
static int
|
||||||
pidfile_verify(struct pidfh *pfh)
|
pidfile_verify(const struct pidfh *pfh)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
|
||||||
@ -114,25 +121,33 @@ pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
|
|||||||
fd = flopen(pfh->pf_path,
|
fd = flopen(pfh->pf_path,
|
||||||
O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
|
O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
|
||||||
if (fd == -1) {
|
if (fd == -1) {
|
||||||
count = 0;
|
if (errno == EWOULDBLOCK) {
|
||||||
|
if (pidptr == NULL) {
|
||||||
|
errno = EEXIST;
|
||||||
|
} else {
|
||||||
|
count = 20;
|
||||||
rqtp.tv_sec = 0;
|
rqtp.tv_sec = 0;
|
||||||
rqtp.tv_nsec = 5000000;
|
rqtp.tv_nsec = 5000000;
|
||||||
if (errno == EWOULDBLOCK && pidptr != NULL) {
|
for (;;) {
|
||||||
again:
|
errno = pidfile_read(pfh->pf_path,
|
||||||
errno = pidfile_read(pfh->pf_path, pidptr);
|
pidptr);
|
||||||
if (errno == 0)
|
if (errno != EAGAIN || --count == 0)
|
||||||
errno = EEXIST;
|
break;
|
||||||
else if (errno == EAGAIN) {
|
|
||||||
if (++count <= 3) {
|
|
||||||
nanosleep(&rqtp, 0);
|
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->pf_path);
|
||||||
free(pfh);
|
free(pfh);
|
||||||
|
errno = error;
|
||||||
return (NULL);
|
return (NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remember file information, so in pidfile_write() we are sure we write
|
* Remember file information, so in pidfile_write() we are sure we write
|
||||||
* to the proper descriptor.
|
* to the proper descriptor.
|
||||||
@ -251,3 +266,14 @@ pidfile_remove(struct pidfh *pfh)
|
|||||||
|
|
||||||
return (_pidfile_remove(pfh, 1));
|
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