Merge branch 'develop' into 1.2.1-binlog_router_trx
This commit is contained in:
@ -86,6 +86,10 @@
|
||||
#include <ini.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <sys/file.h>
|
||||
|
||||
#define STRING_BUFFER_SIZE 1024
|
||||
#define PIDFD_CLOSED -1
|
||||
|
||||
/** for procname */
|
||||
#if !defined(_GNU_SOURCE)
|
||||
@ -139,7 +143,7 @@ static char datadir[PATH_MAX+1] = "";
|
||||
static bool datadir_defined = false; /*< If the datadir was already set */
|
||||
/* The data directory we created for this gateway instance */
|
||||
static char pidfile[PATH_MAX+1] = "";
|
||||
|
||||
static int pidfd = PIDFD_CLOSED;
|
||||
|
||||
/**
|
||||
* exit flag for log flusher.
|
||||
@ -181,6 +185,7 @@ static void log_flush_shutdown(void);
|
||||
static void log_flush_cb(void* arg);
|
||||
static int write_pid_file(); /* write MaxScale pidfile */
|
||||
static void unlink_pidfile(void); /* remove pidfile */
|
||||
static void unlock_pidfile();
|
||||
static void libmysqld_done(void);
|
||||
static bool file_write_header(FILE* outfile);
|
||||
static bool file_write_footer(FILE* outfile);
|
||||
@ -207,7 +212,7 @@ static bool resolve_maxscale_conf_fname(
|
||||
|
||||
static char* check_dir_access(char* dirname,bool,bool);
|
||||
static int set_user();
|
||||
|
||||
bool pid_file_exists();
|
||||
/** SSL multi-threading functions and structures */
|
||||
|
||||
static SPINLOCK* ssl_locks;
|
||||
@ -1816,8 +1821,22 @@ int main(int argc, char **argv)
|
||||
"MaxScale is running in process %i",
|
||||
getpid())));
|
||||
|
||||
/** Check if a MaxScale process is already running */
|
||||
if(pid_file_exists())
|
||||
{
|
||||
/** There is a process with the PID of the maxscale.pid file running.
|
||||
* Assuming that this is an already running MaxScale process, we
|
||||
* should exit with an error code. */
|
||||
rc = MAXSCALE_ALREADYRUNNING;
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
/* Write process pid into MaxScale pidfile */
|
||||
write_pid_file();
|
||||
if(write_pid_file() != 0)
|
||||
{
|
||||
rc = MAXSCALE_ALREADYRUNNING;
|
||||
goto return_main;
|
||||
}
|
||||
|
||||
/* Init MaxScale poll system */
|
||||
poll_init();
|
||||
@ -1922,6 +1941,7 @@ int main(int argc, char **argv)
|
||||
|
||||
unload_all_modules();
|
||||
/* Remove Pidfile */
|
||||
unlock_pidfile();
|
||||
unlink_pidfile();
|
||||
|
||||
return_main:
|
||||
@ -1983,6 +2003,21 @@ static void log_flush_cb(
|
||||
"Finished MaxScale log flusher.")));
|
||||
}
|
||||
|
||||
static void unlock_pidfile()
|
||||
{
|
||||
if(pidfd != PIDFD_CLOSED)
|
||||
{
|
||||
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
|
||||
*/
|
||||
@ -2000,6 +2035,131 @@ static void unlink_pidfile(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the maxscale.pid file exists and has a valid PID in it. If one has already been
|
||||
* written and a MaxScale process is running, this instance of MaxScale should shut down.
|
||||
* @return True if the conditions for starting MaxScale are not met and false if
|
||||
* no PID file was found or there is no process running with the PID of the maxscale.pid
|
||||
* file. If false is returned, this process should continue normally.
|
||||
*/
|
||||
bool pid_file_exists()
|
||||
{
|
||||
char pathbuf[PATH_MAX+1];
|
||||
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
|
||||
char pidbuf[STRING_BUFFER_SIZE];
|
||||
pid_t pid;
|
||||
bool lock_failed = false;
|
||||
|
||||
snprintf(pathbuf, PATH_MAX, "%s/maxscale.pid",get_piddir());
|
||||
pathbuf[PATH_MAX] = '\0';
|
||||
|
||||
if(access(pathbuf,F_OK) != 0)
|
||||
return false;
|
||||
|
||||
if(access(pathbuf,R_OK) == 0)
|
||||
{
|
||||
int fd, b;
|
||||
|
||||
if((fd = open(pathbuf, O_RDWR)) == -1)
|
||||
{
|
||||
char* logerr = "Failed to open PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
return true;
|
||||
}
|
||||
if(flock(fd,LOCK_EX|LOCK_NB))
|
||||
{
|
||||
if(errno != EWOULDBLOCK)
|
||||
{
|
||||
char* logerr = "Failed to lock PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
close(fd);
|
||||
return true;
|
||||
}
|
||||
lock_failed = true;
|
||||
}
|
||||
|
||||
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 */
|
||||
char* logerr = "PID file read from '%s'. File was empty.\n"
|
||||
"If the file is the correct PID file and no other MaxScale processes "
|
||||
"are running, please remove it manually and start MaxScale again.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return true;
|
||||
}
|
||||
|
||||
pidbuf[b < sizeof(pidbuf) ? b : sizeof(pidbuf) - 1] = '\0';
|
||||
pid = strtol(pidbuf,NULL,0);
|
||||
|
||||
if(pid < 1)
|
||||
{
|
||||
/** Bad PID */
|
||||
char* logerr = "PID file read from '%s'. File contents not valid.\n"
|
||||
"If the file is the correct PID file and no other MaxScale processes "
|
||||
"are running, please remove it manually and start MaxScale again.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return true;
|
||||
}
|
||||
|
||||
if(kill(pid,0) == -1)
|
||||
{
|
||||
if(errno == ESRCH)
|
||||
{
|
||||
/** no such process, old PID file */
|
||||
if(lock_failed)
|
||||
{
|
||||
char* logerr = "Locking the PID file '%s' failed. Read PID from file and no process found with PID %d. "
|
||||
"Confirm that no other process holds the lock on the PID file.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf,pid);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, 0);
|
||||
close(fd);
|
||||
}
|
||||
return lock_failed;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* logerr = "Failed to check the existence of process %d read from file '%s'";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pid,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* logerr = "MaxScale is already running. Process id: %d. "
|
||||
"Use another location for the PID file to run multiple instances of MaxScale on the same machine.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pid);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, 0);
|
||||
unlock_pidfile();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
char* logerr = "Cannot open PID file '%s', no read permissions. "
|
||||
"Please confirm that the user running MaxScale has read permissions on the file.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pathbuf);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write process pid into pidfile anc close it
|
||||
* Parameters:
|
||||
@ -2009,33 +2169,58 @@ static void unlink_pidfile(void)
|
||||
*/
|
||||
|
||||
static int write_pid_file() {
|
||||
|
||||
int fd = -1;
|
||||
char logbuf[STRING_BUFFER_SIZE + PATH_MAX];
|
||||
char pidstr[STRING_BUFFER_SIZE];
|
||||
|
||||
snprintf(pidfile, PATH_MAX, "%s/maxscale.pid",get_piddir());
|
||||
|
||||
fd = open(pidfile, O_WRONLY | O_CREAT | O_TRUNC, 0777);
|
||||
if (fd == -1) {
|
||||
fprintf(stderr, "MaxScale failed to open pidFile %s: error %d, %s\n", pidfile, errno, strerror(errno));
|
||||
return 1;
|
||||
} else {
|
||||
char pidstr[50]="";
|
||||
/* truncate pidfile content */
|
||||
if (ftruncate(fd, 0) == -1) {
|
||||
fprintf(stderr, "MaxScale failed to truncate pidfile %s: error %d, %s\n", pidfile, errno, strerror(errno));
|
||||
if(pidfd == PIDFD_CLOSED)
|
||||
{
|
||||
int fd = -1;
|
||||
|
||||
fd = open(pidfile, O_WRONLY | O_CREAT, 0777);
|
||||
if (fd == -1) {
|
||||
char* logerr = "Failed to open PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(flock(fd,LOCK_EX|LOCK_NB))
|
||||
{
|
||||
if(errno == EWOULDBLOCK)
|
||||
{
|
||||
snprintf(logbuf,sizeof(logbuf),"Failed to lock PID file '%s', another process is holding a lock on it. "
|
||||
"Please confirm that no other MaxScale process is using the same PID file location.",pidfile);
|
||||
}
|
||||
|
||||
snprintf(pidstr, sizeof(pidstr)-1, "%d", getpid());
|
||||
|
||||
if (pwrite(fd, 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));
|
||||
/* close file and return */
|
||||
close(fd);
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
snprintf(logbuf,sizeof(logbuf),"Failed to lock PID file '%s'.",pidfile);
|
||||
}
|
||||
|
||||
/* close file */
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
pidfd = fd;
|
||||
}
|
||||
|
||||
/* truncate pidfile content */
|
||||
if (ftruncate(pidfd, 0)) {
|
||||
char* logerr = "MaxScale failed to truncate PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(pidstr, sizeof(pidstr)-1, "%d", getpid());
|
||||
|
||||
if (pwrite(pidfd, pidstr, strlen(pidstr), 0) != (ssize_t)strlen(pidstr)) {
|
||||
char* logerr = "MaxScale failed to write into PID file '%s'.";
|
||||
snprintf(logbuf,sizeof(logbuf),logerr,pidfile);
|
||||
print_log_n_stderr(true, true, logbuf, logbuf, errno);
|
||||
unlock_pidfile();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* success */
|
||||
|
@ -67,7 +67,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
}
|
||||
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
|
||||
fprintf(stderr, "service_alloc() failed\n");
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
fprintf(stderr, "Failed adding %s@%s(%lu)\n", username, ret_ip, fix_ipv4);
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -114,7 +114,7 @@ int set_and_get_single_mysql_users_ipv4(char *username, unsigned long ipv4, char
|
||||
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
|
||||
if (!fetch_data)
|
||||
return 1;
|
||||
@ -198,7 +198,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
}
|
||||
if ((service = (SERVICE *)calloc(1, sizeof(SERVICE))) == NULL) {
|
||||
fprintf(stderr, "service_alloc() failed\n");
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
if(!setipaddress(&client_addr.sin_addr, from)) {
|
||||
fprintf(stderr, "setipaddress failed for host [%s]\n", from);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@ -216,7 +216,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
if ((data = (MYSQL_session *) calloc(1, sizeof(MYSQL_session))) == NULL) {
|
||||
fprintf(stderr, "MYSQL_session alloc failed\n");
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -235,7 +235,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
else
|
||||
strncpy(data->db, "",MYSQL_DATABASE_MAXLEN);
|
||||
|
||||
/* freed by dcb_free(dcb) */
|
||||
/* freed by dcb_close(dcb) */
|
||||
dcb->data = data;
|
||||
|
||||
// the routine returns 1 on success
|
||||
@ -264,7 +264,7 @@ int set_and_get_mysql_users_wildcards(char *username, char *hostname, char *pass
|
||||
|
||||
users_free(mysql_users);
|
||||
free(service);
|
||||
dcb_free(dcb);
|
||||
dcb_close(dcb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -63,6 +63,9 @@ static char* server_groups[] = {
|
||||
NULL
|
||||
};
|
||||
|
||||
int config_load(char *);
|
||||
int module_create_feedback_report(GWBUF **buffer, MODULES *modules, FEEDBACK_CONF *cfg);
|
||||
int do_http_post(GWBUF *buffer, void *cfg);
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
|
@ -37,7 +37,7 @@
|
||||
#define MAXSCALE_BADCONFIG 1 /* Configuration fiel error */
|
||||
#define MAXSCALE_NOLIBRARY 2 /* No embedded library found */
|
||||
#define MAXSCALE_NOSERVICES 3 /* No servics are running */
|
||||
#define MAXSCALE_HOMELESS 4 /* No MaxScale Home */
|
||||
#define MAXSCALE_ALREADYRUNNING 4 /* MaxScale is already runing */
|
||||
#define MAXSCALE_BADARG 5 /* Bad command line argument */
|
||||
#define MAXSCALE_INTERNALERROR 6 /* Internal error, see error log */
|
||||
#endif
|
||||
|
Reference in New Issue
Block a user