Add pidfile support (closes: #1651)
This commit is contained in:
parent
4d632694e6
commit
de6f874d5e
|
@ -60,6 +60,8 @@ Optional arguments:
|
|||
-a, --auth pass Simple text password (only in VRRPv2)
|
||||
-f, --foreground Execute uvrrpd in foreground
|
||||
-s, --script Path of hook script (default /etc/uvrrpd/uvrrpd-switch.sh)
|
||||
-F --pidfile Create pid file 'name
|
||||
Default /var/run/uvrrp_${vrid}.pid
|
||||
-d, --debug
|
||||
-h, --help
|
||||
```
|
||||
|
|
138
uvrrpd.c
138
uvrrpd.c
|
@ -23,6 +23,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#include "uvrrpd.h"
|
||||
#include "vrrp.h"
|
||||
|
@ -35,12 +36,19 @@
|
|||
|
||||
#include "log.h"
|
||||
|
||||
/* global constants */
|
||||
unsigned long reg = 0UL;
|
||||
int background = 1;
|
||||
char *loglevel = NULL;
|
||||
char *pidfile_name = NULL;
|
||||
|
||||
/* local methods */
|
||||
static void signal_handler(int sig);
|
||||
static void signal_setup(void);
|
||||
static int pidfile_init(int vrid);
|
||||
static void pidfile_unlink(void);
|
||||
static void pidfile_check(int vrid);
|
||||
static void pidfile(int vrid);
|
||||
|
||||
/**
|
||||
* main() - entry point
|
||||
|
@ -64,6 +72,12 @@ int main(int argc, char *argv[])
|
|||
if (! !vrrp_options(&vrrp, &vnet, argc, argv))
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
/* pidfile init && check */
|
||||
if (pidfile_init(vrrp.vrid) != 0)
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
pidfile_check(vrrp.vrid);
|
||||
|
||||
/* logs */
|
||||
log_open("uvrrpd", (char const *) loglevel);
|
||||
|
||||
|
@ -96,6 +110,10 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
chdir("/");
|
||||
|
||||
|
||||
/* pidfile */
|
||||
pidfile(vrrp.vrid);
|
||||
|
||||
/* process */
|
||||
set_bit(KEEP_GOING, ®);
|
||||
while (test_bit(KEEP_GOING, ®) && !vrrp_process(&vrrp, &vnet));
|
||||
|
@ -105,7 +123,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
if (vnet.family == AF_INET)
|
||||
vrrp_arp_cleanup(&vnet);
|
||||
else /* AF_INET6 */
|
||||
else /* AF_INET6 */
|
||||
vrrp_na_cleanup(&vnet);
|
||||
|
||||
vrrp_cleanup(&vrrp);
|
||||
|
@ -114,6 +132,8 @@ int main(int argc, char *argv[])
|
|||
|
||||
log_close();
|
||||
free(loglevel);
|
||||
pidfile_unlink();
|
||||
free(pidfile_name);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@ -201,3 +221,119 @@ static void signal_setup(void)
|
|||
|
||||
sigprocmask(SIG_BLOCK, &sa.sa_mask, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* pidfile_init()
|
||||
*/
|
||||
static int pidfile_init(int vrid)
|
||||
{
|
||||
int max_len = NAME_MAX + PATH_MAX;
|
||||
if (pidfile_name == NULL) {
|
||||
pidfile_name = malloc(max_len);
|
||||
if (pidfile_name == NULL) {
|
||||
log_error("vrid %d :: malloc - %m", vrid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(pidfile_name, max_len, PIDFILE_NAME, vrid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* pidfile_unlink() - remove pidfile
|
||||
*/
|
||||
static void pidfile_unlink(void)
|
||||
{
|
||||
if (pidfile_name)
|
||||
unlink(pidfile_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* pidfile_check()
|
||||
*/
|
||||
static void pidfile_check(int vrid)
|
||||
{
|
||||
struct flock fl;
|
||||
int err, fd;
|
||||
|
||||
fd = open(pidfile_name, O_RDONLY | O_CLOEXEC);
|
||||
if (fd < 0) {
|
||||
if (errno == ENOENT)
|
||||
return;
|
||||
fprintf(stderr, "vrid %d :: error opening PID file %s: %m\n",
|
||||
vrid, pidfile_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
|
||||
err = fcntl(fd, F_GETLK, &fl);
|
||||
close(fd);
|
||||
if (err < 0) {
|
||||
fprintf(stderr, "vrid %d :: error getting PID file %s lock: %m",
|
||||
vrid, pidfile_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (fl.l_type == F_UNLCK)
|
||||
return;
|
||||
|
||||
fprintf(stderr, "vrid %d :: uvrrpd is already running (pid %d)\n", vrid,
|
||||
(int) fl.l_pid);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/**
|
||||
* pid_file()
|
||||
*/
|
||||
static void pidfile(int vrid)
|
||||
{
|
||||
struct flock fl;
|
||||
char buf[16];
|
||||
int err, fd;
|
||||
|
||||
fd = open(pidfile_name,
|
||||
O_WRONLY | O_CREAT | O_CLOEXEC, S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
log_error("vrid %d :: error opening PID file %s: %m\n", vrid,
|
||||
pidfile_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
fl.l_type = F_WRLCK;
|
||||
fl.l_whence = SEEK_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
|
||||
err = fcntl(fd, F_SETLK, &fl);
|
||||
if (err < 0) {
|
||||
if (errno == EACCES || errno == EAGAIN) {
|
||||
log_error("vrid %d :: uvrrpd is already running\n",
|
||||
vrid);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
log_error("vrid %d :: error setting PID file %s lock: %m\n",
|
||||
vrid, pidfile_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
atexit(pidfile_unlink);
|
||||
|
||||
err = snprintf(buf, sizeof(buf), "%d\n", (int) getpid());
|
||||
if (err < 0) {
|
||||
perror("snprintf");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
err = write(fd, buf, err);
|
||||
if (err < 0) {
|
||||
log_error("vrid %d :: error writing PID to PID file %s: %m\n",
|
||||
vrid, pidfile_name);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
|
2
uvrrpd.h
2
uvrrpd.h
|
@ -24,6 +24,8 @@
|
|||
|
||||
#include "bits.h"
|
||||
|
||||
#define PIDFILE_NAME "/var/run/uvrrpd_%d.pid"
|
||||
|
||||
/**
|
||||
* uvrrpd_control
|
||||
* Enum server control register flags
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
/* from uvrrpd.c */
|
||||
extern int background;
|
||||
extern char *loglevel;
|
||||
extern char *pidfile_name;
|
||||
|
||||
/**
|
||||
* vrrp_usage()
|
||||
|
@ -58,9 +59,8 @@ static void vrrp_usage(void)
|
|||
" -a, --auth pass Simple text password (only in VRRPv2)\n"
|
||||
" -f, --foreground Execute uvrrpd in foreground\n"
|
||||
" -s, --script Path of hook script (default /etc/uvrrpd/uvrrpd-switch.sh)\n"
|
||||
#if 0 /* todo */
|
||||
" --pidfile name Create pid file 'name'\n"
|
||||
#endif
|
||||
" -F --pidfile name Create pid file 'name'\n"
|
||||
" Default /var/run/uvrrp_${vrid}.pid\n"
|
||||
" -d, --debug\n" " -h, --help\n");
|
||||
}
|
||||
|
||||
|
@ -84,13 +84,14 @@ int vrrp_options(struct vrrp *vrrp, struct vrrp_net *vnet, int argc,
|
|||
{"auth", required_argument, 0, 'a'},
|
||||
{"foreground", no_argument, 0, 'f'},
|
||||
{"script", required_argument, 0, 's'},
|
||||
{"pidfile", required_argument, 0, 'F'},
|
||||
{"debug", no_argument, 0, 'd'},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{NULL, 0, 0, 0}
|
||||
};
|
||||
|
||||
while ((optc =
|
||||
getopt_long(argc, argv, "v:i:p:t:P:r:6a:fs:dh", opts,
|
||||
getopt_long(argc, argv, "v:i:p:t:P:r:6a:fs:F:dh", opts,
|
||||
NULL)) != EOF) {
|
||||
switch (optc) {
|
||||
|
||||
|
@ -193,6 +194,11 @@ int vrrp_options(struct vrrp *vrrp, struct vrrp_net *vnet, int argc,
|
|||
}
|
||||
break;
|
||||
|
||||
/* pidfile */
|
||||
case 'F':
|
||||
pidfile_name = strndup(optarg, NAME_MAX + PATH_MAX);
|
||||
break;
|
||||
|
||||
/* debug */
|
||||
case 'd':
|
||||
loglevel = strndup("debug", 6);
|
||||
|
|
Loading…
Reference in a new issue