diff --git a/src/ckpool.c b/src/ckpool.c index f9d3511e..fa96d6f1 100644 --- a/src/ckpool.c +++ b/src/ckpool.c @@ -699,13 +699,14 @@ static bool write_pid(ckpool_t *ckp, const char *path, pid_t pid) return true; } -static void create_process_unixsock(proc_instance_t *pi) +static void name_process_sockname(unixsock_t *us, proc_instance_t *pi) { - unixsock_t *us = &pi->us; - ckpool_t *ckp = pi->ckp; - us->path = strdup(pi->ckp->socket_dir); realloc_strcat(&us->path, pi->sockname); +} + +static void open_process_sock(ckpool_t *ckp, proc_instance_t *pi, unixsock_t *us) +{ LOGDEBUG("Opening %s", us->path); us->sockd = open_unix_server(us->path); if (unlikely(us->sockd < 0)) @@ -714,6 +715,15 @@ static void create_process_unixsock(proc_instance_t *pi) quit(1, "Failed to set %s to group id %d", us->path, ckp->gr_gid); } +static void create_process_unixsock(proc_instance_t *pi) +{ + unixsock_t *us = &pi->us; + ckpool_t *ckp = pi->ckp; + + name_process_sockname(us, pi); + open_process_sock(ckp, pi, us); +} + static void write_namepid(proc_instance_t *pi) { char s[256]; @@ -1031,6 +1041,7 @@ static struct option long_options[] = { {"config", required_argument, 0, 'c'}, {"ckdb-name", required_argument, 0, 'd'}, {"group", required_argument, 0, 'g'}, + {"handover", no_argument, 0, 'H'}, {"help", no_argument, 0, 'h'}, {"killold", no_argument, 0, 'k'}, {"loglevel", required_argument, 0, 'l'}, @@ -1055,7 +1066,7 @@ int main(int argc, char **argv) memset(&ckp, 0, sizeof(ckp)); ckp.loglevel = LOG_NOTICE; - while ((c = getopt_long(argc, argv, "Ac:d:g:hkl:n:pS:s:", long_options, &i)) != -1) { + while ((c = getopt_long(argc, argv, "Ac:d:g:Hhkl:n:pS:s:", long_options, &i)) != -1) { switch (c) { case 'A': ckp.standalone = true; @@ -1069,6 +1080,10 @@ int main(int argc, char **argv) case 'g': ckp.grpnam = optarg; break; + case 'H': + ckp.handover = true; + ckp.killold = true; + break; case 'h': for (j = 0; long_options[j].val; j++) { struct option *jopt = &long_options[j]; @@ -1215,8 +1230,24 @@ int main(int argc, char **argv) ckp.main.ckp = &ckp; ckp.main.processname = strdup("main"); ckp.main.sockname = strdup("listener"); + name_process_sockname(&ckp.main.us, &ckp.main); + if (ckp.handover) { + int sockd = open_unix_client(ckp.main.us.path); + + if (sockd > 0 && send_unix_msg(sockd, "getfd")) { + ckp.oldconnfd = get_fd(sockd); + + close(sockd); + sockd = open_unix_client(ckp.main.us.path); + send_unix_msg(sockd, "shutdown"); + if (ckp.oldconnfd > 0) + LOGWARNING("Inherited old socket with new file descriptor %d!", ckp.oldconnfd); + close(sockd); + } + } + write_namepid(&ckp.main); - create_process_unixsock(&ckp.main); + open_process_sock(&ckp, &ckp.main, &ckp.main.us); launch_logger(&ckp.main); ckp.logfd = fileno(ckp.logfp); diff --git a/src/ckpool.h b/src/ckpool.h index 2d28aa0b..3a15c83f 100644 --- a/src/ckpool.h +++ b/src/ckpool.h @@ -102,6 +102,10 @@ struct ckpool_instance { /* Logfile */ FILE *logfp; int logfd; + /* Connector fd if we inherited it from a running process */ + int oldconnfd; + /* Should we inherit a running instance's socket and shut it down */ + bool handover; /* Logger message queue NOTE: Unique per process */ ckmsgq_t *logger; diff --git a/src/connector.c b/src/connector.c index 0ad53b8b..38375212 100644 --- a/src/connector.c +++ b/src/connector.c @@ -575,7 +575,10 @@ int connector(proc_instance_t *pi) LOGWARNING("%s connector starting", ckp->name); - if (ckp->serverurl) { + if (ckp->oldconnfd > 0) { + extract_sockaddr(ckp->serverurl, &url, &port); + sockd = ckp->oldconnfd; + } else if (ckp->serverurl) { if (!extract_sockaddr(ckp->serverurl, &url, &port)) { LOGWARNING("Failed to extract server address from %s", ckp->serverurl); ret = 1;