Commit dbc71f01 authored by Geoff Simmons's avatar Geoff Simmons

implement the -P option (writing a pid file)

parent f2d8d93b
......@@ -26,7 +26,11 @@ varnishevent_SOURCES = \
format.c \
handler.c \
vtim.h \
vtim.c
vtim.c \
vpf.h \
vpf.c \
flopen.h \
flopen.c
varnishevent_LDADD = \
${PTHREAD_LIBS} ${RT_LIBS} ${LIBM} @VARNISH_LIBS@ \
......
/*-
* Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
* 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
* in this position and unchanged.
* 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 AUTHOR 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 AUTHOR 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.
* Derived from:
* $FreeBSD: head/lib/libutil/flopen.c 184094 2008-10-20 18:11:30Z des $
*/
#include "config.h"
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdarg.h>
#include <string.h>
#include <unistd.h>
#include "flopen.h"
int
flopen(const char *path, int flags, ...)
{
int fd, operation, serrno, trunc;
struct flock lock;
struct stat sb, fsb;
mode_t mode;
#ifdef O_EXLOCK
flags &= ~O_EXLOCK;
#endif
mode = 0;
if (flags & O_CREAT) {
va_list ap;
va_start(ap, flags);
mode = (mode_t)va_arg(ap, int); /* mode_t promoted to int */
va_end(ap);
}
memset(&lock, 0, sizeof lock);
lock.l_type = ((flags & O_ACCMODE) == O_RDONLY) ? F_RDLCK : F_WRLCK;
lock.l_whence = SEEK_SET;
operation = (flags & O_NONBLOCK) ? F_SETLK : F_SETLKW;
trunc = (flags & O_TRUNC);
flags &= ~O_TRUNC;
for (;;) {
if ((fd = open(path, flags, mode)) == -1)
/* non-existent or no access */
return (-1);
if (fcntl(fd, operation, &lock) == -1) {
/* unsupported or interrupted */
serrno = errno;
(void)close(fd);
errno = serrno;
return (-1);
}
if (stat(path, &sb) == -1) {
/* disappeared from under our feet */
(void)close(fd);
continue;
}
if (fstat(fd, &fsb) == -1) {
/* can't happen [tm] */
serrno = errno;
(void)close(fd);
errno = serrno;
return (-1);
}
if (sb.st_dev != fsb.st_dev ||
sb.st_ino != fsb.st_ino) {
/* changed under our feet */
(void)close(fd);
continue;
}
if (trunc && ftruncate(fd, 0) != 0) {
/* can't happen [tm] */
serrno = errno;
(void)close(fd);
errno = serrno;
return (-1);
}
return (fd);
}
}
/* Tests if the given fd is locked through flopen
* If pid is non-NULL, stores the pid of the process holding the lock there
* Returns 1 if the file is locked
* Returns 0 if the file is unlocked
* Returns -1 on error (and errno)
*/
int
fltest(int fd, pid_t *pid)
{
struct flock lock;
memset(&lock, 0, sizeof lock);
lock.l_type = F_WRLCK;
lock.l_whence = SEEK_SET;
if (fcntl(fd, F_GETLK, &lock) == -1)
return (-1);
if (lock.l_type == F_UNLCK)
return (0);
if (pid != NULL)
*pid = lock.l_pid;
return (1);
}
/*-
* Copyright (c) 2007 Dag-Erling Coïdan Smørgrav
* 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
* in this position and unchanged.
* 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 AUTHOR 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 AUTHOR 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.
*
* Derived from:
* $FreeBSD: src/lib/libutil/libutil.h,v 1.44 2007/05/10 15:01:42 des Exp $
*/
#ifndef FLOPEN_H_INCLUDED
#define FLOPEN_H_INCLUDED
int flopen(const char *, int, ...);
int fltest(int fd, pid_t *pid);
#endif
......@@ -60,11 +60,7 @@
#include <errno.h>
#include "vsb.h"
#if 0
#include "vpf.h"
#endif
#include "vqueue.h"
#include "vapi/vsl.h"
#include "vre.h"
#include "miniobj.h"
......@@ -73,6 +69,7 @@
#include "varnishevent.h"
#include "vtim.h"
#include "vpf.h"
#define DEFAULT_CONFIG "/etc/varnishevent.conf"
......@@ -416,14 +413,9 @@ int
main(int argc, char *argv[])
{
int c, errnum, status, a_flag = 0, v_flag = 0, d_flag = 0, D_flag = 0;
#if 0
const char *P_arg = NULL;
#endif
char *w_arg = NULL, *q_arg = NULL, *g_arg = NULL;
char scratch[BUFSIZ];
#if 0
char *P_arg = NULL, *w_arg = NULL, *q_arg = NULL, *g_arg = NULL,
scratch[BUFSIZ];
struct vpf_fh *pfh = NULL;
#endif
struct VSL_data *vsl;
struct VSLQ *vslq;
struct VSM_data *vsm;
......@@ -454,16 +446,14 @@ main(int argc, char *argv[])
exit(EXIT_FAILURE);
#endif
break;
#if 0
case 'P':
P_arg = optarg;
REPLACE(P_arg, optarg);
break;
#endif
case 'V':
VCS_Message("varnishevent");
exit(0);
case 'w':
w_arg = optarg;
REPLACE(w_arg, optarg);
break;
case 'v':
v_flag = 1;
......@@ -501,21 +491,15 @@ main(int argc, char *argv[])
}
}
#if 0
if (P_arg && (pfh = VPF_Open(P_arg, 0644, NULL)) == NULL) {
perror(P_arg);
exit(1);
exit(EXIT_FAILURE);
}
#endif
#ifdef HAVE_DAEMON
if (D_flag && daemon(0, 0) == -1) {
perror("daemon()");
#if 0
if (pfh != NULL)
VPF_Remove(pfh);
#endif
exit(1);
exit(EXIT_FAILURE);
}
#endif
......@@ -529,6 +513,16 @@ main(int argc, char *argv[])
LOG_Log(LOG_INFO, "initializing (%s)", VCS_version);
if (pfh != NULL) {
errno = 0;
if (VPF_Write(pfh) != 0) {
LOG_Log(LOG_CRIT, "Cannot write pid file %s, exiting: %s", P_arg,
strerror(errno));
exit(EXIT_FAILURE);
}
errno = 0;
}
/* XXX: also set grouping in config file */
if (g_arg != NULL) {
grouping = VSLQ_Name2Grouping(g_arg, -1);
......@@ -613,11 +607,6 @@ main(int argc, char *argv[])
/* Install signal handlers */
#include "signals.h"
#if 0
if (pfh != NULL)
VPF_Write(pfh);
#endif
if (w_arg)
strcpy(config.output_file, w_arg);
if (!EMPTY(config.output_file))
......@@ -769,6 +758,12 @@ main(int argc, char *argv[])
FMT_Fini();
AZ(pthread_cond_destroy(&spscq_ready_cond));
AZ(pthread_mutex_destroy(&spscq_ready_lock));
if (pfh != NULL) {
errno = 0;
if (VPF_Remove(pfh) != 0)
LOG_Log(LOG_WARNING, "Could not remove pid file %s: %s", P_arg,
strerror(errno));
}
LOG_Log0(LOG_INFO, "Exiting");
LOG_Close();
......
/*-
* 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.
* Derived from:
* $FreeBSD: head/lib/libutil/pidfile.c 184091 2008-10-20 17:41:08Z des $
*/
#include "config.h"
#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "flopen.h"
#include "vas.h"
#include "vpf.h"
struct vpf_fh {
int pf_fd;
char pf_path[MAXPATHLEN + 1];
dev_t pf_dev;
ino_t pf_ino;
};
static int _VPF_Remove(struct vpf_fh *pfh, int freeit);
static int
vpf_verify(const struct vpf_fh *pfh)
{
struct stat sb;
if (pfh == NULL || pfh->pf_fd == -1)
return (EINVAL);
/*
* 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 (EINVAL);
return (0);
}
static int
vpf_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. */
(void)close(fd);
if (i == -1)
return (error);
buf[i] = '\0';
*pidptr = strtol(buf, &endptr, 10);
if (endptr != &buf[i])
return (EINVAL);
return (0);
}
struct vpf_fh *
VPF_Open(const char *path, mode_t mode, pid_t *pidptr)
{
struct vpf_fh *pfh;
struct stat sb;
int error, fd, len;
pfh = malloc(sizeof(*pfh));
if (pfh == NULL)
return (NULL);
#if 0
if (path == NULL)
len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
"/var/run/%s.pid", getprogname());
else
#endif
{
assert(path != NULL);
len = snprintf(pfh->pf_path, sizeof(pfh->pf_path),
"%s", path);
}
if (len >= (int)sizeof(pfh->pf_path)) {
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 VPF_Write(), so
* VPF_Write() can be called multiple times.
*/
fd = flopen(pfh->pf_path,
O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, mode);
if (fd == -1) {
if (errno == EWOULDBLOCK && pidptr != NULL) {
errno = vpf_read(pfh->pf_path, pidptr);
if (errno == 0)
errno = EEXIST;
}
free(pfh);
return (NULL);
}
/*
* Remember file information, so in VPF_Write() we are sure we write
* to the proper descriptor.
*/
if (fstat(fd, &sb) == -1) {
error = errno;
(void)unlink(pfh->pf_path);
(void)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
VPF_Write(struct vpf_fh *pfh)
{
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 = vpf_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 VPF_Write() are allowed.
*/
if (ftruncate(fd, 0) == -1) {
error = errno;
(void)_VPF_Remove(pfh, 0);
errno = error;
return (-1);
}
error = snprintf(pidstr, sizeof(pidstr), "%ju", (uintmax_t)getpid());
assert(error < sizeof pidstr);
if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
error = errno;
(void)_VPF_Remove(pfh, 0);
errno = error;
return (-1);
}
return (0);
}
int
VPF_Close(struct vpf_fh *pfh)
{
int error;
error = vpf_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
_VPF_Remove(struct vpf_fh *pfh, int freeit)
{
int error;
error = vpf_verify(pfh);
if (error != 0) {
errno = error;
return (-1);
}
if (unlink(pfh->pf_path) == -1)
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
VPF_Remove(struct vpf_fh *pfh)
{
return (_VPF_Remove(pfh, 1));
}
/*-
* 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.
*
* Derived from:
* $FreeBSD: src/lib/libutil/libutil.h,v 1.41 2005/08/24 17:21:38 pjd Exp $
*/
#ifndef VPF_H_INCLUDED
#define VPF_H_INCLUDED
struct vpf_fh;
struct vpf_fh *VPF_Open(const char *path, mode_t mode, pid_t *pidptr);
int VPF_Write(struct vpf_fh *pfh);
int VPF_Close(struct vpf_fh *pfh);
int VPF_Remove(struct vpf_fh *pfh);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment