Browse Source

Install signal handlers which push the signal to the top process which will try to gracefully shut down each child process

master
Con Kolivas 11 years ago
parent
commit
a615b56d76
  1. 63
      src/ckpool.c
  2. 2
      src/connector.c
  3. 6
      src/generator.c
  4. 5
      src/libckpool.c
  5. 18
      src/stratifier.c

63
src/ckpool.c

@ -134,6 +134,15 @@ static void rm_namepid(proc_instance_t *pi)
unlink(s); unlink(s);
} }
/* Disable signal handlers for child processes, but simply pass them onto the
* parent process to shut down cleanly. */
static void childsighandler(int sig)
{
pid_t ppid = getppid();
kill(ppid, sig);
}
static void launch_process(proc_instance_t *pi) static void launch_process(proc_instance_t *pi)
{ {
pid_t pid; pid_t pid;
@ -142,8 +151,15 @@ static void launch_process(proc_instance_t *pi)
if (pid < 0) if (pid < 0)
quit(1, "Failed to fork %s in launch_process", pi->processname); quit(1, "Failed to fork %s in launch_process", pi->processname);
if (!pid) { if (!pid) {
struct sigaction handler;
int ret; int ret;
handler.sa_handler = &childsighandler;
handler.sa_flags = 0;
sigemptyset(&handler.sa_mask);
sigaction(SIGTERM, &handler, NULL);
sigaction(SIGINT, &handler, NULL);
rename_proc(pi->processname); rename_proc(pi->processname);
write_namepid(pi); write_namepid(pi);
ret = pi->process(pi); ret = pi->process(pi);
@ -160,23 +176,47 @@ static void clean_up(ckpool_t *ckp)
dealloc(ckp->socket_dir); dealloc(ckp->socket_dir);
} }
static void __shutdown_children(ckpool_t *ckp, int sig)
{
pthread_cancel(ckp->pth_watchdog);
join_pthread(ckp->pth_watchdog);
if (!kill(ckp->generator.pid, 0))
kill(ckp->generator.pid, sig);
if (!kill(ckp->stratifier.pid, 0))
kill(ckp->stratifier.pid, sig);
if (!kill(ckp->connector.pid, 0))
kill(ckp->connector.pid, sig);
}
static void shutdown_children(ckpool_t *ckp, int sig) static void shutdown_children(ckpool_t *ckp, int sig)
{ {
pthread_cancel(ckp->pth_watchdog); pthread_cancel(ckp->pth_watchdog);
join_pthread(ckp->pth_watchdog); join_pthread(ckp->pth_watchdog);
kill(ckp->generator.pid, sig);
kill(ckp->stratifier.pid, sig); __shutdown_children(ckp, sig);
kill(ckp->connector.pid, sig);
} }
static void sighandler(int sig) static void sighandler(int sig)
{ {
pthread_cancel(global_ckp->pth_watchdog);
join_pthread(global_ckp->pth_watchdog);
/* First attempt, send a shutdown message */
send_proc(&global_ckp->generator, "shutdown");
send_proc(&global_ckp->stratifier, "shutdown");
send_proc(&global_ckp->connector, "shutdown");
if (sig != 9) { if (sig != 9) {
shutdown_children(global_ckp, 15); /* Wait a second, then send SIGTERM */
pthread_cancel(global_ckp->pth_listener); sleep(1);
__shutdown_children(global_ckp, SIGTERM);
/* Wait another second, then send SIGKILL */
sleep(1); sleep(1);
__shutdown_children(global_ckp, SIGKILL);
pthread_cancel(global_ckp->pth_listener);
} else { } else {
shutdown_children(global_ckp, 9); __shutdown_children(global_ckp, SIGKILL);
exit(1); exit(1);
} }
} }
@ -367,11 +407,6 @@ int main(int argc, char **argv)
/* Ignore sigpipe */ /* Ignore sigpipe */
signal(SIGPIPE, SIG_IGN); signal(SIGPIPE, SIG_IGN);
handler.sa_handler = &sighandler;
handler.sa_flags = 0;
sigemptyset(&handler.sa_mask);
sigaction(SIGTERM, &handler, NULL);
sigaction(SIGINT, &handler, NULL);
ret = mkdir(ckp.socket_dir, 0700); ret = mkdir(ckp.socket_dir, 0700);
if (ret && errno != EEXIST) if (ret && errno != EEXIST)
@ -408,6 +443,12 @@ int main(int argc, char **argv)
launch_process(&ckp.stratifier); launch_process(&ckp.stratifier);
launch_process(&ckp.connector); launch_process(&ckp.connector);
handler.sa_handler = &sighandler;
handler.sa_flags = 0;
sigemptyset(&handler.sa_mask);
sigaction(SIGTERM, &handler, NULL);
sigaction(SIGINT, &handler, NULL);
test_functions(&ckp); test_functions(&ckp);
create_pthread(&ckp.pth_watchdog, watchdog, &ckp); create_pthread(&ckp.pth_watchdog, watchdog, &ckp);

2
src/connector.c

@ -512,5 +512,5 @@ out:
send_proc(&ckp->main, "shutdown"); send_proc(&ckp->main, "shutdown");
sleep(1); sleep(1);
} }
return ret; exit(ret);
} }

6
src/generator.c

@ -46,8 +46,10 @@ retry:
goto retry; goto retry;
} }
LOGDEBUG("Generator received request: %s", buf); LOGDEBUG("Generator received request: %s", buf);
if (!strncasecmp(buf, "shutdown", 8)) if (!strncasecmp(buf, "shutdown", 8)) {
ret = 0;
goto out; goto out;
}
if (!strncasecmp(buf, "getbase", 7)) { if (!strncasecmp(buf, "getbase", 7)) {
if (!gen_gbtbase(cs, &gbt)) { if (!gen_gbtbase(cs, &gbt)) {
LOGWARNING("Failed to get block template from %s:%s", LOGWARNING("Failed to get block template from %s:%s",
@ -154,5 +156,5 @@ out:
send_proc(&ckp->main, "shutdown"); send_proc(&ckp->main, "shutdown");
sleep(1); sleep(1);
} }
return ret; exit(ret);
} }

5
src/libckpool.c

@ -56,10 +56,7 @@ void create_pthread(pthread_t *thread, void *(*start_routine)(void *), void *arg
void join_pthread(pthread_t thread) void join_pthread(pthread_t thread)
{ {
int ret = pthread_join(thread, NULL); pthread_join(thread, NULL);
if (unlikely(ret))
quit(1, "Failed to pthread_join");
} }

18
src/stratifier.c

@ -582,7 +582,7 @@ static void drop_client(int id)
ck_uilock(&instance_lock); ck_uilock(&instance_lock);
} }
static int strat_loop(ckpool_t *ckp, proc_instance_t *pi) static int stratum_loop(ckpool_t *ckp, proc_instance_t *pi)
{ {
int sockd, ret = 0, selret; int sockd, ret = 0, selret;
unixsock_t *us = &pi->us; unixsock_t *us = &pi->us;
@ -626,9 +626,10 @@ retry:
goto retry; goto retry;
} }
LOGDEBUG("Stratifier received request: %s", buf); LOGDEBUG("Stratifier received request: %s", buf);
if (!strncasecmp(buf, "shutdown", 8)) if (!strncasecmp(buf, "shutdown", 8)) {
ret = 0;
goto out; goto out;
else if (!strncasecmp(buf, "update", 6)) { } else if (!strncasecmp(buf, "update", 6)) {
update_base(ckp); update_base(ckp);
goto reset; goto reset;
} else if (!strncasecmp(buf, "dropclient", 10)) { } else if (!strncasecmp(buf, "dropclient", 10)) {
@ -1422,7 +1423,7 @@ int stratifier(proc_instance_t *pi)
pthread_t pth_blockupdate, pth_stratum_receiver, pth_stratum_sender; pthread_t pth_blockupdate, pth_stratum_receiver, pth_stratum_sender;
pthread_t pth_statsupdate; pthread_t pth_statsupdate;
ckpool_t *ckp = pi->ckp; ckpool_t *ckp = pi->ckp;
int ret = 0; int ret;
/* Store this for use elsewhere */ /* Store this for use elsewhere */
hex2bin(scriptsig_header_bin, scriptsig_header, 41); hex2bin(scriptsig_header_bin, scriptsig_header, 41);
@ -1450,7 +1451,12 @@ int stratifier(proc_instance_t *pi)
cklock_init(&share_lock); cklock_init(&share_lock);
strat_loop(ckp, pi); ret = stratum_loop(ckp, pi);
LOGINFO("%s stratifier exiting with return code %d", ckp->name, ret);
if (ret) {
send_proc(&ckp->main, "shutdown");
sleep(1);
}
return ret; exit(ret);
} }

Loading…
Cancel
Save