Added PID file locks and cleaned up code.

This commit is contained in:
Markus Makela
2015-08-24 15:01:34 +03:00
parent 1dd22a4d2c
commit 0a33174803

View File

@ -86,6 +86,9 @@
#include <ini.h> #include <ini.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/file.h>
#define STRING_BUFFER_SIZE 1024
/** for procname */ /** for procname */
#if !defined(_GNU_SOURCE) #if !defined(_GNU_SOURCE)
@ -139,7 +142,7 @@ static char datadir[PATH_MAX+1] = "";
static bool datadir_defined = false; /*< If the datadir was already set */ static bool datadir_defined = false; /*< If the datadir was already set */
/* The data directory we created for this gateway instance */ /* The data directory we created for this gateway instance */
static char pidfile[PATH_MAX+1] = ""; static char pidfile[PATH_MAX+1] = "";
static int pidfd = -1;
/** /**
* exit flag for log flusher. * exit flag for log flusher.
@ -181,6 +184,7 @@ static void log_flush_shutdown(void);
static void log_flush_cb(void* arg); static void log_flush_cb(void* arg);
static int write_pid_file(); /* write MaxScale pidfile */ static int write_pid_file(); /* write MaxScale pidfile */
static void unlink_pidfile(void); /* remove pidfile */ static void unlink_pidfile(void); /* remove pidfile */
static void unlock_pidfile();
static void libmysqld_done(void); static void libmysqld_done(void);
static bool file_write_header(FILE* outfile); static bool file_write_header(FILE* outfile);
static bool file_write_footer(FILE* outfile); static bool file_write_footer(FILE* outfile);
@ -1827,7 +1831,12 @@ int main(int argc, char **argv)
} }
/* Write process pid into MaxScale pidfile */ /* Write process pid into MaxScale pidfile */
write_pid_file(); if(write_pid_file() != 0)
{
skygw_log_write(LE,"Error: Failed to write PID file. Exiting.");
rc = MAXSCALE_ALREADYRUNNING;
goto return_main;
}
/* Init MaxScale poll system */ /* Init MaxScale poll system */
poll_init(); poll_init();
@ -1932,6 +1941,7 @@ int main(int argc, char **argv)
unload_all_modules(); unload_all_modules();
/* Remove Pidfile */ /* Remove Pidfile */
unlock_pidfile();
unlink_pidfile(); unlink_pidfile();
return_main: return_main:
@ -1993,6 +2003,19 @@ static void log_flush_cb(
"Finished MaxScale log flusher."))); "Finished MaxScale log flusher.")));
} }
static void unlock_pidfile()
{
if(pidfd != -1)
if(flock(pidfd,LOCK_UN|LOCK_NB) != 0)
{
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
char* logerr = "Failed to unlock PID file '%s'.";
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
}
close(pidfd);
}
/** /**
* Unlink pid file, called at program exit * Unlink pid file, called at program exit
*/ */
@ -2020,49 +2043,67 @@ static void unlink_pidfile(void)
bool pid_file_exists() bool pid_file_exists()
{ {
char pathbuf[PATH_MAX+1]; char pathbuf[PATH_MAX+1];
char pidbuf[1024]; char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
char pidbuf[STRING_BUFFER_SIZE];
pid_t pid; pid_t pid;
int fd,b;
snprintf(pathbuf, PATH_MAX, "%s/maxscale.pid",piddir?piddir:default_piddir); snprintf(pathbuf, PATH_MAX, "%s/maxscale.pid",piddir?piddir:default_piddir);
pathbuf[PATH_MAX] = '\0';
if(access(pathbuf,F_OK) != 0) if(access(pathbuf,F_OK) != 0)
return false; return false;
if(access(pathbuf,R_OK) == 0) if(access(pathbuf,R_OK) == 0)
{ {
int fd, b;
if((fd = open(pathbuf, O_RDONLY)) == -1) if((fd = open(pathbuf, O_RDONLY)) == -1)
{ {
char* logerr = "Failed to open PID file."; char* logerr = "Failed to open PID file '%s'.";
print_log_n_stderr(true, true, logerr, logerr, errno); snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
return true; return true;
} }
if(flock(fd,LOCK_EX|LOCK_NB) != 0)
if((b = read(fd,pidbuf,1024)) == -1)
{ {
close(fd); close(fd);
char* logerr = "Failed to read from PID file."; char* logerr = "Failed to lock PID file '%s'.";
print_log_n_stderr(true, true, logerr, logerr, errno); snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
return true; return true;
} }
close(fd);
if(b == 0 ) pidfd = fd;
b = read(fd,pidbuf,sizeof(pidbuf));
if(b == -1)
{
char* logerr = "Failed to read from PID file '%s'.";
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
unlock_pidfile();
return true;
}
else if(b == 0)
{ {
/** Empty file */ /** Empty file */
char* logerr = "PID file was empty."; char* logerr = "PID file read from '%s'. File was empty.";
print_log_n_stderr(true, true, logerr, logerr, 0); snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
unlock_pidfile();
return true; return true;
} }
pidbuf[b < 1024? b:1023] = '\0'; pidbuf[b < sizeof(pidbuf) ? b : sizeof(pidbuf) - 1] = '\0';
pid = strtol(pidbuf,NULL,0); pid = strtol(pidbuf,NULL,0);
if(pid < 1) if(pid < 1)
{ {
/** Bad PID */ /** Bad PID */
char* logerr = "PID file contents not valid."; char* logerr = "PID file read from '%s'. File contents not valid.";
print_log_n_stderr(true, true, logerr, logerr, 0); snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
unlock_pidfile();
return true; return true;
} }
@ -2075,25 +2116,26 @@ bool pid_file_exists()
} }
else else
{ {
char* logerr = "Failed to send signal to process %d"; char* logerr = "Failed to check the existence of process %d";
char logbuf[1024]; snprintf(logbuf,sizeof(logbuf),logerr,pid);
sprintf(logbuf,logerr,pid);
print_log_n_stderr(true, true, logbuf, logbuf, errno); print_log_n_stderr(true, true, logbuf, logbuf, errno);
unlock_pidfile();
} }
} }
else else
{ {
char* logerr = "MaxScale is already running. Process id: %d"; char* logerr = "MaxScale is already running. Process id: %d";
char logbuf[1024]; snprintf(logbuf,sizeof(logbuf),logerr,pid);
sprintf(logbuf,logerr,pid);
print_log_n_stderr(true, true, logbuf, logbuf, 0); print_log_n_stderr(true, true, logbuf, logbuf, 0);
unlock_pidfile();
return true; return true;
} }
} }
else else
{ {
char* logerr = "Cannot open PID file, no read permissions."; char* logerr = "Cannot open PID file '%s', no read permissions.";
print_log_n_stderr(true, true, logerr, logerr, 0); snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
return true; return true;
} }
return true; return true;
@ -2108,33 +2150,46 @@ bool pid_file_exists()
*/ */
static int write_pid_file() { static int write_pid_file() {
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
char pidstr[STRING_BUFFER_SIZE];
if(pidfd == -1)
{
int fd = -1; int fd = -1;
snprintf(pidfile, PATH_MAX, "%s/maxscale.pid",get_piddir()); snprintf(pidfile, PATH_MAX, "%s/maxscale.pid",get_piddir());
fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0777); fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0777);
if (fd == -1) { if (fd == -1 && errno != ENOENT) {
fprintf(stderr, "MaxScale failed to open pidFile %s: error %d, %s\n", pidfile, errno, strerror(errno)); char* logerr = "Failed to open PID file '%s'.";
return 1; snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
} else { print_log_n_stderr(true, true, logbuf, logbuf, errno);
char pidstr[50]=""; return -1;
}
if(flock(fd,LOCK_EX|LOCK_NB) != 0)
{
char* logerr = "Failed to lock PID file '%s'.";
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
print_log_n_stderr(true, true, logbuf, logbuf, errno);
close(fd);
return -1;
}
pidfd = fd;
}
/* truncate pidfile content */ /* truncate pidfile content */
if (ftruncate(fd, 0) == -1) { if (ftruncate(pidfd, 0) == -1) {
fprintf(stderr, "MaxScale failed to truncate pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno)); fprintf(stderr, "MaxScale failed to truncate pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno));
unlock_pidfile();
return -1;
} }
snprintf(pidstr, sizeof(pidstr)-1, "%d", getpid()); snprintf(pidstr, sizeof(pidstr)-1, "%d", getpid());
if (pwrite(fd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) { if (pwrite(pidfd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
fprintf(stderr, "MaxScale failed to write into pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno)); fprintf(stderr, "MaxScale failed to write into pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno));
/* close file and return */ /* close file and return */
close(fd); unlock_pidfile();
return 1; return -1;
}
/* close file */
close(fd);
} }
/* success */ /* success */