diff --git a/include/proxysql_glovars.hpp b/include/proxysql_glovars.hpp index 08e8df027..e6486dbb1 100644 --- a/include/proxysql_glovars.hpp +++ b/include/proxysql_glovars.hpp @@ -30,6 +30,7 @@ class ProxySQL_GlobalVariables { char *datadir; char *admindb; char *errorlog; + char *pid; struct { unsigned long long start_time; bool gdbg; diff --git a/src/Makefile b/src/Makefile index ed0c5c59d..e9a0aa5e6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,6 +9,10 @@ MARIADB_IDIR=$(MARIADB_PATH)/include MARIADB_LDIR=$(MARIADB_PATH)/libmariadb +DAEMONPATH=$(DEPS_PATH)/libdaemon/libdaemon +DAEMONPATH_IDIR=$(DAEMONPATH) +DAEMONPATH_LDIR=$(DAEMONPATH)/libdaemon/.libs + #LIBEVENT_PATH=$(DEPS_PATH)/libevent/libevent #LIBEVENT_IDIR=$(LIBEVENT_PATH)/include #LIBEVENT_LDIR=$(LIBEVENT_PATH)/.libs @@ -42,13 +46,13 @@ IDIR=../include LDIR=../lib #IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) -I$(LIBEVENT_IDIR) $(GLIB_IDIRS) $(LIBCONFIG_IDIR) #LDIRS=-L$(LDIR) -L$(JEMALLOC_LDIR) -L$(MARIADB_LDIR) -L$(LIBEVENT_LDIR) $(GLIB_LDIRS) $(LIBCONFIG_LDIR) -IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -LDIRS=-L$(LDIR) -L$(JEMALLOC_LDIR) $(LIBCONFIG_LDIR) -L$(RE2_PATH)/obj -L$(INJECTION_PATH) -L$(LIBEVENT_LDIR) -L$(MARIADB_LDIR) +IDIRS=-I$(IDIR) -I$(JEMALLOC_IDIR) -I$(MARIADB_IDIR) $(LIBCONFIG_IDIR) -I$(DAEMONPATH_IDIR) +LDIRS=-L$(LDIR) -L$(JEMALLOC_LDIR) $(LIBCONFIG_LDIR) -L$(RE2_PATH)/obj -L$(INJECTION_PATH) -L$(LIBEVENT_LDIR) -L$(MARIADB_LDIR) -L$(DAEMONPATH_LDIR) #LDIRS=-L$(LDIR) -L$(JEMALLOC_LDIR) -L$(MARIADB_LDIR) $(GLIB_LDIRS) $(LIBCONFIG_LDIR) CFLAGS=-std=c++0x $(IDIRS) $(OPTZ) $(DEBUG) -LIBS=-rdynamic -Wl,-Bstatic -lconfig -lproxysql -ljemalloc -lconfig++ -lre2 -linjection -levent -lmariadbclient -Wl,-Bdynamic -lpthread -lm -lz -lrt -ldl -lcrypto -lssl $(EXTRALINK) +LIBS=-rdynamic -Wl,-Bstatic -lconfig -lproxysql -ldaemon -ljemalloc -lconfig++ -lre2 -linjection -levent -lmariadbclient -Wl,-Bdynamic -lpthread -lm -lz -lrt -ldl -lcrypto -lssl $(EXTRALINK) #LIBS=-rdynamic -Wl,-Bstatic -lproxysql -ljemalloc -levent $(GLIB_LIB) -Wl,-Bdynamic -ldl -lpthread -lm -lz -lrt LIBPROXYSQLAR=$(LDIR)/libproxysql.a diff --git a/src/main.cpp b/src/main.cpp index 527aad582..6cc69fa81 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -6,12 +6,29 @@ //#define PROXYSQL_EXTERN #include "cpp.h" + +#include +#include +#include +#include +#include + // MariaDB client library redefines dlerror(), see https://mariadb.atlassian.net/browse/CONC-101 #ifdef dlerror #undef dlerror #endif +time_t laststart; +pid_t pid; + +static const char * proxysql_pid_file() { + static char fn[512]; + snprintf(fn, sizeof(fn), "%s", daemon_pid_file_ident); + return fn; +} + + /* void ProxySQL_Main_init_SSL_module() { SSL_library_init(); @@ -169,6 +186,9 @@ void ProxySQL_Main_process_global_variables(int argc, const char **argv) { GloVars.errorlog=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.log")+2); sprintf(GloVars.errorlog,"%s/%s",GloVars.datadir, (char *)"proxysql.log"); + GloVars.pid=(char *)malloc(strlen(GloVars.datadir)+strlen((char *)"proxysql.pid")+2); + sprintf(GloVars.pid,"%s/%s",GloVars.datadir, (char *)"proxysql.pid"); + if (GloVars.__cmd_proxysql_initial==true) { std::cerr << "Renaming database file " << GloVars.admindb << endl; char *newpath=(char *)malloc(strlen(GloVars.admindb)+8); @@ -194,7 +214,7 @@ void ProxySQL_Main_init_main_modules() { void ProxySQL_Main_init_Admin_module() { GloAdmin = new ProxySQL_Admin(); GloAdmin->init(); - GloAdmin->flush_error_log(); +// GloAdmin->flush_error_log(); GloAdmin->print_version(); } @@ -284,6 +304,7 @@ void ProxySQL_Main_shutdown_all_modules() { void ProxySQL_Main_init() { #ifdef DEBUG + GloVars.global.gdbg=false; glovars.has_debug=true; #else glovars.has_debug=false; @@ -351,12 +372,159 @@ void ProxySQL_Main_init_phase4___shutdown() { } +void ProxySQL_daemonize_phase1(char *argv0) { + int rc; + daemon_pid_file_ident=GloVars.pid; + daemon_log_ident=daemon_ident_from_argv0(argv0); + rc=chdir(GloVars.datadir); + if (rc) { + daemon_log(LOG_ERR, "Could not chdir into datadir: %s . Error: %s", GloVars.datadir, strerror(errno)); + exit(EXIT_FAILURE); + } + daemon_pid_file_proc=proxysql_pid_file; + pid=daemon_pid_file_is_running(); + if (pid>=0) { + daemon_log(LOG_ERR, "Daemon already running on PID file %u", pid); + exit(EXIT_FAILURE); + } + if (daemon_retval_init() < 0) { + daemon_log(LOG_ERR, "Failed to create pipe."); + exit(EXIT_FAILURE); + } +} + + +void ProxySQL_daemonize_wait_daemon() { + int ret; + /* Wait for 20 seconds for the return value passed from the daemon process */ + if ((ret = daemon_retval_wait(20)) < 0) { + daemon_log(LOG_ERR, "Could not recieve return value from daemon process: %s", strerror(errno)); + exit(EXIT_FAILURE); + } + + if (ret) { + daemon_log(LOG_ERR, "Daemon returned %i as return value.", ret); + } + exit(ret); +} + + +bool ProxySQL_daemonize_phase2() { + int rc; + /* Close FDs */ + if (daemon_close_all(-1) < 0) { + daemon_log(LOG_ERR, "Failed to close all file descriptors: %s", strerror(errno)); + + /* Send the error condition to the parent process */ + daemon_retval_send(1); + return false; + } + + rc=chdir(GloVars.datadir); + if (rc) { + daemon_log(LOG_ERR, "Could not chdir into datadir: %s . Error: %s", GloVars.datadir, strerror(errno)); + exit(EXIT_FAILURE); + } + /* Create the PID file */ + if (daemon_pid_file_create() < 0) { + daemon_log(LOG_ERR, "Could not create PID file (%s).", strerror(errno)); + daemon_retval_send(2); + return false; + } + + /* Send OK to parent process */ + daemon_retval_send(0); + GloAdmin->flush_error_log(); + proxy_error("Starting ProxySQL\n"); + daemon_log(LOG_INFO, "Sucessfully started"); + + return true; +} + +bool ProxySQL_daemonize_phase3() { + int rc; + int status; + proxy_error("Angel process started ProxySQL process %d\n", pid); + rc=waitpid(pid, &status, 0); + if (rc==-1) { + perror("waitpid"); + //proxy_error("[FATAL]: waitpid: %s\n", perror("waitpid")); + exit(EXIT_FAILURE); + } + rc=WIFEXITED(status); + if (rc) { // client exit()ed + rc=WEXITSTATUS(status); + if (rc==0) { + proxy_error("Shutdown angel process\n"); + exit(EXIT_SUCCESS); + } else { + proxy_error("ProxySQL exited with code %d . Restarting!\n", rc); + return false;; + } + } else { + proxy_error("ProxySQL crashed. Restarting!\n"); + return false; + } + return true; +} + int main(int argc, const char * argv[]) { ProxySQL_Main_init(); ProxySQL_Main_process_global_variables(argc, argv); + + if (GloVars.global.foreground==false) { + + ProxySQL_daemonize_phase1((char *)argv[0]); + + /* Do the fork */ + if ((pid = daemon_fork()) < 0) { + /* Exit on error */ + daemon_retval_done(); + return EXIT_FAILURE; + + } else if (pid) { /* The parent */ + + ProxySQL_daemonize_wait_daemon(); + + } else { /* The daemon */ + + if (ProxySQL_daemonize_phase2()==false) { + goto finish; + } + + } + + laststart=0; +// if (glovars.proxy_restart_on_error) { + if (true) { +gotofork: + if (laststart) { + proxy_error("Angel process is waiting %d seconds before starting a new ProxySQL process\n", glovars.proxy_restart_delay); + sleep(glovars.proxy_restart_delay); + } + laststart=time(NULL); + pid = fork(); + if (pid < 0) { + proxy_error("[FATAL]: Error in fork()\n"); + return EXIT_FAILURE; + } + + if (pid) { + + if (ProxySQL_daemonize_phase3()==false) { + goto gotofork; + } + + } + } + + + + } + __start_label: ProxySQL_Main_init_phase2___not_started(); @@ -385,6 +553,12 @@ __shutdown: goto __start_label; } +finish: + daemon_log(LOG_INFO, "Exiting..."); + daemon_retval_send(255); + daemon_signal_done(); + daemon_pid_file_remove(); + l_mem_destroy(__thr_sfp); return 0; }