From 0c552bab29bd968fdc44d800f7da7cf5522d2d70 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Thu, 27 Aug 2015 14:22:58 +0300 Subject: [PATCH 1/2] Fix to MXS-35: https://mariadb.atlassian.net/browse/MXS-35 The parent process now correctly returns the value from the child process. --- server/core/gateway.c | 57 +++++++++++++++++++++++++++++++++++++++++- server/core/gw_utils.c | 5 ++-- server/include/gw.h | 2 +- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/server/core/gateway.c b/server/core/gateway.c index 2eceea4b2..a79fddfbf 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -1056,6 +1056,9 @@ int main(int argc, char **argv) int n_services; int eno = 0; /*< local variable for errno */ int opt; + int daemon_pipe[2]; + bool parent_process; + int child_status; void** threads = NULL; /*< thread list */ char mysql_home[PATH_MAX+1]; char datadir_arg[10+PATH_MAX+1]; /*< '--datadir=' + PATH_MAX */ @@ -1301,6 +1304,13 @@ int main(int argc, char **argv) } else { + if(pipe(daemon_pipe) == -1) + { + fprintf(stderr,"Error: Failed to create pipe for inter-process communication: %d %s",errno,strerror(errno)); + rc = MAXSCALE_INTERNALERROR; + goto return_main; + } + /*< * Maxscale must be daemonized before opening files, initializing * embedded MariaDB and in general, as early as possible. @@ -1433,7 +1443,37 @@ int main(int argc, char **argv) rc = MAXSCALE_INTERNALERROR; goto return_main; } - gw_daemonize(); + + /** Daemonize the process and wait for the child process to notify + * the parent process of its exit status. */ + parent_process = gw_daemonize(); + + if(parent_process) + { + int nread = read(daemon_pipe[0],(void*)&child_status,sizeof(int)); + close(daemon_pipe[1]); + close(daemon_pipe[0]); + + if(nread == -1) + { + char* logerr = "Failed to read data from child process pipe."; + print_log_n_stderr(true, true, logerr, logerr, errno); + exit(MAXSCALE_INTERNALERROR); + } + else if(nread == 0) + { + /** Child process has exited or closed write pipe */ + char* logerr = "No data read from child process pipe."; + print_log_n_stderr(true, true, logerr, logerr, 0); + exit(MAXSCALE_INTERNALERROR); + } + + exit(child_status); + } + + /** This is the child process and we can close the read end of + * the pipe. */ + close(daemon_pipe[0]); } /*< * Set signal handlers for SIGHUP, SIGTERM, SIGINT and critical signals like SIGSEGV. @@ -1907,6 +1947,13 @@ int main(int argc, char **argv) CRYPTO_set_id_callback(pthread_self); #endif + /** + * Successful start, notify the parent process that it can exit. + */ + ss_dassert(rc == MAXSCALE_SHUTDOWN); + write(daemon_pipe[1],&rc,sizeof(int)); + close(daemon_pipe[1]); + MaxScaleStarted = time(0); /*< * Serve clients. @@ -1945,6 +1992,14 @@ int main(int argc, char **argv) unlink_pidfile(); return_main: + + if(daemon_mode && rc != MAXSCALE_SHUTDOWN) + { + /** Notify the parent process that an error has occurred */ + write(daemon_pipe[1],&rc,sizeof(int)); + close(daemon_pipe[1]); + } + if (threads) free(threads); if (cnf_file_path) diff --git a/server/core/gw_utils.c b/server/core/gw_utils.c index 5d4fb5ed2..1a412370c 100644 --- a/server/core/gw_utils.c +++ b/server/core/gw_utils.c @@ -141,7 +141,7 @@ setipaddress(struct in_addr *a, char *p) { * Daemonize the process by forking and putting the process into the * background. */ -void gw_daemonize(void) { +bool gw_daemonize(void) { pid_t pid; pid = fork(); @@ -153,13 +153,14 @@ void gw_daemonize(void) { if (pid != 0) { /* exit from main */ - exit(0); + return true; } if (setsid() < 0) { fprintf(stderr, "setsid() error %s\n", strerror(errno)); exit(1); } + return false; } /** diff --git a/server/include/gw.h b/server/include/gw.h index b51bb0e2a..4f61d4512 100644 --- a/server/include/gw.h +++ b/server/include/gw.h @@ -74,7 +74,7 @@ #include "dcb.h" -void gw_daemonize(void); +bool gw_daemonize(void); int do_read_dcb(DCB *dcb); void MySQLListener(int epfd, char *config_bind); int MySQLAccept(DCB *listener); From bbc0116cd24bef34b78e238cd11041755960e8c7 Mon Sep 17 00:00:00 2001 From: Markus Makela Date: Tue, 15 Sep 2015 10:52:37 +0300 Subject: [PATCH 2/2] Moved the writing to and closing of the parent-child pipe to a separate function. --- server/core/gateway.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/server/core/gateway.c b/server/core/gateway.c index a79fddfbf..7580c4a68 100644 --- a/server/core/gateway.c +++ b/server/core/gateway.c @@ -213,6 +213,7 @@ static bool resolve_maxscale_conf_fname( static char* check_dir_access(char* dirname,bool,bool); static int set_user(); bool pid_file_exists(); +void write_child_exit_code(int fd, int code); /** SSL multi-threading functions and structures */ static SPINLOCK* ssl_locks; @@ -1450,8 +1451,8 @@ int main(int argc, char **argv) if(parent_process) { - int nread = read(daemon_pipe[0],(void*)&child_status,sizeof(int)); close(daemon_pipe[1]); + int nread = read(daemon_pipe[0],(void*)&child_status,sizeof(int)); close(daemon_pipe[0]); if(nread == -1) @@ -1951,8 +1952,7 @@ int main(int argc, char **argv) * Successful start, notify the parent process that it can exit. */ ss_dassert(rc == MAXSCALE_SHUTDOWN); - write(daemon_pipe[1],&rc,sizeof(int)); - close(daemon_pipe[1]); + write_child_exit_code(daemon_pipe[1], rc); MaxScaleStarted = time(0); /*< @@ -1996,8 +1996,7 @@ return_main: if(daemon_mode && rc != MAXSCALE_SHUTDOWN) { /** Notify the parent process that an error has occurred */ - write(daemon_pipe[1],&rc,sizeof(int)); - close(daemon_pipe[1]); + write_child_exit_code(daemon_pipe[1], rc); } if (threads) @@ -2488,3 +2487,14 @@ static int set_user(char* user) return rval; } +/** + * Write the exit status of the child process to the parent process. + * @param fd File descriptor to write to + * @param code Exit status of the child process + */ +void write_child_exit_code(int fd, int code) +{ + /** Notify the parent process that an error has occurred */ + write(fd, &code, sizeof (int)); + close(fd); +} \ No newline at end of file