Add a family of functions for reliable pidfiles handling.
Idea from: jmg Discussed on: arch@
This commit is contained in:
parent
473f777e4d
commit
a5fe3401b9
@ -8,15 +8,16 @@ CFLAGS+=-DLIBC_SCCS -I${.CURDIR} -I${.CURDIR}/../libc/gen/
|
|||||||
CFLAGS+=-DINET6
|
CFLAGS+=-DINET6
|
||||||
SRCS= _secure_path.c auth.c fparseln.c humanize_number.c login.c \
|
SRCS= _secure_path.c auth.c fparseln.c humanize_number.c login.c \
|
||||||
login_auth.c login_cap.c login_class.c login_crypt.c login_ok.c \
|
login_auth.c login_cap.c login_class.c login_crypt.c login_ok.c \
|
||||||
login_times.c login_tty.c logout.c logwtmp.c property.c pty.c \
|
login_times.c login_tty.c logout.c logwtmp.c \
|
||||||
pw_util.c realhostname.c stub.c \
|
pidfile.c property.c pty.c pw_util.c realhostname.c stub.c \
|
||||||
trimdomain.c uucplock.c
|
trimdomain.c uucplock.c
|
||||||
INCS= libutil.h login_cap.h
|
INCS= libutil.h login_cap.h
|
||||||
|
|
||||||
MAN+= login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
|
MAN+= login.3 login_auth.3 login_tty.3 logout.3 logwtmp.3 pty.3 \
|
||||||
login_cap.3 login_class.3 login_times.3 login_ok.3 \
|
login_cap.3 login_class.3 login_times.3 login_ok.3 \
|
||||||
_secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
|
_secure_path.3 uucplock.3 property.3 auth.3 realhostname.3 \
|
||||||
realhostname_sa.3 trimdomain.3 fparseln.3 humanize_number.3
|
realhostname_sa.3 trimdomain.3 fparseln.3 humanize_number.3 \
|
||||||
|
pidfile.3
|
||||||
MAN+= login.conf.5 auth.conf.5
|
MAN+= login.conf.5 auth.conf.5
|
||||||
MLINKS+= property.3 properties_read.3 property.3 properties_free.3
|
MLINKS+= property.3 properties_read.3 property.3 properties_free.3
|
||||||
MLINKS+= property.3 property_find.3
|
MLINKS+= property.3 property_find.3
|
||||||
@ -39,5 +40,9 @@ MLINKS+=login_ok.3 auth_ttyok.3 login_ok.3 auth_hostok.3 \
|
|||||||
MLINKS+=login_auth.3 auth_checknologin.3 login_auth.3 auth_cat.3
|
MLINKS+=login_auth.3 auth_checknologin.3 login_auth.3 auth_cat.3
|
||||||
MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_lock_txfr.3 \
|
MLINKS+=uucplock.3 uu_lock.3 uucplock.3 uu_lock_txfr.3 \
|
||||||
uucplock.3 uu_unlock.3 uucplock.3 uu_lockerr.3
|
uucplock.3 uu_unlock.3 uucplock.3 uu_lockerr.3
|
||||||
|
MLINKS+=pidfile.3 pidfile_open.3 \
|
||||||
|
pidfile.3 pidfile_write.3 \
|
||||||
|
pidfile.3 pidfile_close.3 \
|
||||||
|
pidfile.3 pidfile_remove.3
|
||||||
|
|
||||||
.include <bsd.lib.mk>
|
.include <bsd.lib.mk>
|
||||||
|
@ -49,6 +49,16 @@ typedef struct _property {
|
|||||||
char *value;
|
char *value;
|
||||||
} *properties;
|
} *properties;
|
||||||
|
|
||||||
|
#ifdef _SYS_PARAM_H_
|
||||||
|
/* for pidfile.c */
|
||||||
|
struct pidfh {
|
||||||
|
int pf_fd;
|
||||||
|
char pf_path[MAXPATHLEN + 1];
|
||||||
|
__dev_t pf_dev;
|
||||||
|
ino_t pf_ino;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Avoid pulling in all the include files for no need */
|
/* Avoid pulling in all the include files for no need */
|
||||||
struct termios;
|
struct termios;
|
||||||
struct winsize;
|
struct winsize;
|
||||||
@ -102,6 +112,13 @@ struct passwd *pw_scan(const char *_line, int _flags);
|
|||||||
const char *pw_tempname(void);
|
const char *pw_tempname(void);
|
||||||
int pw_tmp(int _mfd);
|
int pw_tmp(int _mfd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef _SYS_PARAM_H_
|
||||||
|
struct pidfh *pidfile_open(const char *path, mode_t mode, pid_t *pidptr);
|
||||||
|
int pidfile_write(struct pidfh *pfh);
|
||||||
|
int pidfile_close(struct pidfh *pfh);
|
||||||
|
int pidfile_remove(struct pidfh *pfh);
|
||||||
|
#endif
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#define UU_LOCK_INUSE (1)
|
#define UU_LOCK_INUSE (1)
|
||||||
|
227
lib/libutil/pidfile.3
Normal file
227
lib/libutil/pidfile.3
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
.\" Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
|
.\" All rights reserved.
|
||||||
|
.\"
|
||||||
|
.\" Redistribution and use in source and binary forms, with or without
|
||||||
|
.\" modification, are permitted provided that the following conditions
|
||||||
|
.\" are met:
|
||||||
|
.\" 1. Redistributions of source code must retain the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer.
|
||||||
|
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
.\" notice, this list of conditions and the following disclaimer in the
|
||||||
|
.\" documentation and/or other materials provided with the distribution.
|
||||||
|
.\"
|
||||||
|
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
.\" SUCH DAMAGE.
|
||||||
|
.\"
|
||||||
|
.\" $FreeBSD$
|
||||||
|
.\"
|
||||||
|
.Dd August 22, 2005
|
||||||
|
.Dt PIDFILE 3
|
||||||
|
.Os
|
||||||
|
.Sh NAME
|
||||||
|
.Nm pidfile_open ,
|
||||||
|
.Nm pidfile_write ,
|
||||||
|
.Nm pidfile_close ,
|
||||||
|
.Nm pidfile_remove
|
||||||
|
.Nd library for PID files handling
|
||||||
|
.Sh LIBRARY
|
||||||
|
.Lb libutil
|
||||||
|
.Sh SYNOPSIS
|
||||||
|
.In sys/param.h
|
||||||
|
.In libutil.h
|
||||||
|
.Ft struct pidfh *
|
||||||
|
.Fn pidfile_open "const char *path" "mode_t mode" "pid_t *pidptr"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_write "struct pidfh *pfh"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_close "struct pidfh *pfh"
|
||||||
|
.Ft int
|
||||||
|
.Fn pidfile_remove "struct pidfh *pfh"
|
||||||
|
.Sh DESCRIPTION
|
||||||
|
The
|
||||||
|
.Nm libpidfile
|
||||||
|
library provides functions for daemons to handle file with PID.
|
||||||
|
It uses
|
||||||
|
.Xr flock 2
|
||||||
|
to lock pidfile and detect already running daemons.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function opens (or creates) a file specified by
|
||||||
|
.Fa path
|
||||||
|
argument and locks it with
|
||||||
|
.Xr flock 2
|
||||||
|
syscall.
|
||||||
|
If file can not be locked, PID of already running daemon is returned in
|
||||||
|
.Fa pidptr
|
||||||
|
argument (if it is not NULL).
|
||||||
|
The function doesn't write process' PID into the file here, so it can be
|
||||||
|
used before fork()ing and exit with proper error message when needed.
|
||||||
|
If
|
||||||
|
.Fa path
|
||||||
|
argument is NULL,
|
||||||
|
.Pa /var/run/<progname>.pid
|
||||||
|
file will be used.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_write
|
||||||
|
function write process' PID into previously opened file.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_close
|
||||||
|
function closes pidfile.
|
||||||
|
It should be used after daemon fork()s to start a child process.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_remove
|
||||||
|
function closes and removes pidfile.
|
||||||
|
.Sh RETURN VALUES
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function return a valid pointer to a pidfh structure on success or
|
||||||
|
.Dv NULL
|
||||||
|
if an error occurs.
|
||||||
|
If an error does occur,
|
||||||
|
.Va errno
|
||||||
|
will be set.
|
||||||
|
.Rv -std pidfile_write pidfile_close pidfile_remove
|
||||||
|
.Sh EXAMPLES
|
||||||
|
The following example shows in which order those functions should be used.
|
||||||
|
.Bd -literal
|
||||||
|
struct pidfh *pfh;
|
||||||
|
pid_t otherpid, childpid;
|
||||||
|
|
||||||
|
pfh = pidfile_open("/var/run/daemon.pid", 0644, &otherpid);
|
||||||
|
if (pfh == NULL) {
|
||||||
|
if (errno == EEXIST)
|
||||||
|
errx(EXIT_FAILURE, "Daemon already running, pid: %d.", otherpid);
|
||||||
|
/* If we cannot create pidfile from other reasons, only warn. */
|
||||||
|
warn("Cannot open or create pidfile");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (daemon(0, 0) == -1) {
|
||||||
|
warn("Cannot daemonize");
|
||||||
|
pidfile_remove(pfh);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pidfile_write(pfh);
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
/* Do work. */
|
||||||
|
childpid = fork();
|
||||||
|
switch (childpid) {
|
||||||
|
case -1:
|
||||||
|
syslog(LOG_ERR, "Cannot fork(): %s.", strerror(errno));
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
pidfile_close(pfh);
|
||||||
|
/* Do child work. */
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
syslog(LOG_INFO, "Child %d started.", childpid);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pidfile_remove(pfh);
|
||||||
|
exit(EXIT_SUCCESS);
|
||||||
|
.Ed
|
||||||
|
.Sh ERRORS
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EEXIST
|
||||||
|
Some process already holds the lock on the given pidfile, which means,
|
||||||
|
daemon is already running.
|
||||||
|
.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.
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_open
|
||||||
|
function may also fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr fstat 2 ,
|
||||||
|
.Xr open 2 ,
|
||||||
|
.Xr read 2
|
||||||
|
routines.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_write
|
||||||
|
function will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EDOOFUS
|
||||||
|
Inproper function use.
|
||||||
|
Probably called before
|
||||||
|
.Fn pidfile_open .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_write
|
||||||
|
function may also fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr fstat 2 ,
|
||||||
|
.Xr ftruncate 2 ,
|
||||||
|
.Xr write 2
|
||||||
|
routines.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_close
|
||||||
|
function may fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr close 2 ,
|
||||||
|
.Xr fstat 2
|
||||||
|
routines.
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_remove
|
||||||
|
function will fail if:
|
||||||
|
.Bl -tag -width Er
|
||||||
|
.It Bq Er EDOOFUS
|
||||||
|
Inproper function use.
|
||||||
|
Probably called not from the process which made
|
||||||
|
.Fn pidfile_write .
|
||||||
|
.El
|
||||||
|
.Pp
|
||||||
|
The
|
||||||
|
.Fn pidfile_remove
|
||||||
|
function may also fail and set
|
||||||
|
.Va errno
|
||||||
|
for any errors specified for the
|
||||||
|
.Xr close 2 ,
|
||||||
|
.Xr flock 2 ,
|
||||||
|
.Xr fstat 2 ,
|
||||||
|
.Xr write 2 ,
|
||||||
|
.Xr unlink 2
|
||||||
|
routines.
|
||||||
|
.Pp
|
||||||
|
.Sh SEE ALSO
|
||||||
|
.Xr flock 2 ,
|
||||||
|
.Xr open 2 ,
|
||||||
|
.Xr daemon 3
|
||||||
|
.Sh AUTHORS
|
||||||
|
.An -nosplit
|
||||||
|
The
|
||||||
|
.Xr pidfile 3
|
||||||
|
functionality is based on ideas from
|
||||||
|
.An John-Mark Gurney Aq jmg@FreeBSD.org .
|
||||||
|
.Pp
|
||||||
|
The code and manual page was written by
|
||||||
|
.An Pawel Jakub Dawidek Aq pjd@FreeBSD.org .
|
246
lib/libutil/pidfile.c
Normal file
246
lib/libutil/pidfile.c
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 Pawel Jakub Dawidek <pjd@FreeBSD.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/cdefs.h>
|
||||||
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/file.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <libutil.h>
|
||||||
|
|
||||||
|
static int _pidfile_remove(struct pidfh *pfh, int freeit);
|
||||||
|
|
||||||
|
static int
|
||||||
|
pidfile_verify(struct pidfh *pfh)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
if (pfh == NULL || pfh->pf_fd == -1)
|
||||||
|
return (EDOOFUS);
|
||||||
|
/*
|
||||||
|
* Check remembered descriptor.
|
||||||
|
*/
|
||||||
|
if (fstat(pfh->pf_fd, &sb) == -1)
|
||||||
|
return (errno);
|
||||||
|
if (sb.st_dev != pfh->pf_dev || sb.st_ino != pfh->pf_ino)
|
||||||
|
return (EDOOFUS);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pidfile_read(const char *path, pid_t *pidptr)
|
||||||
|
{
|
||||||
|
char buf[16], *endptr;
|
||||||
|
int error, fd, i;
|
||||||
|
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd == -1)
|
||||||
|
return (errno);
|
||||||
|
|
||||||
|
i = read(fd, buf, sizeof(buf) - 1);
|
||||||
|
error = errno; /* Remember errno in case close() wants to change it. */
|
||||||
|
close(fd);
|
||||||
|
if (i == -1)
|
||||||
|
return (error);
|
||||||
|
buf[i] = '\0';
|
||||||
|
|
||||||
|
*pidptr = strtol(buf, &endptr, 10);
|
||||||
|
if (endptr != &buf[i])
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pidfh *
|
||||||
|
pidfile_open(const char *path, mode_t mode, pid_t *pidptr)
|
||||||
|
{
|
||||||
|
struct pidfh *pfh;
|
||||||
|
struct stat sb;
|
||||||
|
int error, fd;
|
||||||
|
|
||||||
|
pfh = malloc(sizeof(*pfh));
|
||||||
|
if (pfh == NULL)
|
||||||
|
return (NULL);
|
||||||
|
|
||||||
|
if (path == NULL) {
|
||||||
|
snprintf(pfh->pf_path, sizeof(pfh->pf_path), "/var/run/%s.pid",
|
||||||
|
getprogname());
|
||||||
|
} else {
|
||||||
|
strlcpy(pfh->pf_path, path, sizeof(pfh->pf_path));
|
||||||
|
}
|
||||||
|
if (strlen(pfh->pf_path) == sizeof(pfh->pf_path) - 1) {
|
||||||
|
free(pfh);
|
||||||
|
errno = ENAMETOOLONG;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Open the PID file and obtain exclusive lock.
|
||||||
|
* We truncate PID file here only to remove old PID immediatelly,
|
||||||
|
* PID file will be truncated again in pidfile_write(), so
|
||||||
|
* pidfile_write() can be called multiple times.
|
||||||
|
*/
|
||||||
|
fd = open(pfh->pf_path,
|
||||||
|
O_WRONLY | O_CREAT | O_EXLOCK | O_TRUNC | O_NONBLOCK, mode);
|
||||||
|
if (fd == -1) {
|
||||||
|
if (errno == EWOULDBLOCK && pidptr != NULL) {
|
||||||
|
errno = pidfile_read(pfh->pf_path, pidptr);
|
||||||
|
if (errno == 0)
|
||||||
|
errno = EEXIST;
|
||||||
|
}
|
||||||
|
free(pfh);
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* Remember file information, so in pidfile_write() we are sure we write
|
||||||
|
* to the proper descriptor.
|
||||||
|
*/
|
||||||
|
if (fstat(fd, &sb) == -1) {
|
||||||
|
error = errno;
|
||||||
|
unlink(pfh->pf_path);
|
||||||
|
close(fd);
|
||||||
|
free(pfh);
|
||||||
|
errno = error;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
pfh->pf_fd = fd;
|
||||||
|
pfh->pf_dev = sb.st_dev;
|
||||||
|
pfh->pf_ino = sb.st_ino;
|
||||||
|
|
||||||
|
return (pfh);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pidfile_write(struct pidfh *pfh)
|
||||||
|
{
|
||||||
|
struct stat sb;
|
||||||
|
char pidstr[16];
|
||||||
|
int error, fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check remembered descriptor, so we don't overwrite some other
|
||||||
|
* file if pidfile was closed and descriptor reused.
|
||||||
|
*/
|
||||||
|
errno = pidfile_verify(pfh);
|
||||||
|
if (errno != 0) {
|
||||||
|
/*
|
||||||
|
* Don't close descriptor, because we are not sure if it's ours.
|
||||||
|
*/
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
fd = pfh->pf_fd;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Truncate PID file, so multiple calls of pidfile_write() are allowed.
|
||||||
|
*/
|
||||||
|
if (ftruncate(fd, 0) == -1) {
|
||||||
|
error = errno;
|
||||||
|
_pidfile_remove(pfh, 0);
|
||||||
|
errno = error;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
snprintf(pidstr, sizeof(pidstr), "%u", getpid());
|
||||||
|
if (write(fd, pidstr, strlen(pidstr)) != (ssize_t)strlen(pidstr)) {
|
||||||
|
error = errno;
|
||||||
|
_pidfile_remove(pfh, 0);
|
||||||
|
errno = error;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pidfile_close(struct pidfh *pfh)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = pidfile_verify(pfh);
|
||||||
|
if (error != 0) {
|
||||||
|
errno = error;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (close(pfh->pf_fd) == -1)
|
||||||
|
error = errno;
|
||||||
|
free(pfh);
|
||||||
|
if (error != 0) {
|
||||||
|
errno = error;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
_pidfile_remove(struct pidfh *pfh, int freeit)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = pidfile_verify(pfh);
|
||||||
|
if (error != 0) {
|
||||||
|
errno = error;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (unlink(pfh->pf_path) == -1)
|
||||||
|
error = errno;
|
||||||
|
if (flock(pfh->pf_fd, LOCK_UN) == -1) {
|
||||||
|
if (error == 0)
|
||||||
|
error = errno;
|
||||||
|
}
|
||||||
|
if (close(pfh->pf_fd) == -1) {
|
||||||
|
if (error == 0)
|
||||||
|
error = errno;
|
||||||
|
}
|
||||||
|
if (freeit)
|
||||||
|
free(pfh);
|
||||||
|
else
|
||||||
|
pfh->pf_fd = -1;
|
||||||
|
if (error != 0) {
|
||||||
|
errno = error;
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pidfile_remove(struct pidfh *pfh)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (_pidfile_remove(pfh, 1));
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user