From: phk Date: Thu, 3 Aug 2006 11:46:52 +0000 (+0000) Subject: Imlement stopping and restarting of child process. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2c4772dd31322f98d06183720a3d1e740055da8b;p=varnish Imlement stopping and restarting of child process. Not as useful as it will be yet, see ticket 22 git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@622 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishd/mgt_child.c b/varnish-cache/bin/varnishd/mgt_child.c index ccffc5c6..71fa133e 100644 --- a/varnish-cache/bin/varnishd/mgt_child.c +++ b/varnish-cache/bin/varnishd/mgt_child.c @@ -23,6 +23,7 @@ #include "mgt.h" static pid_t child_pid = -1; +static pid_t mgr_pid; static int child_fds[2]; static unsigned child_should_run; static pthread_t child_listen_thread; @@ -30,20 +31,24 @@ static pthread_t child_poker_thread; static pthread_mutex_t child_mtx; static pthread_cond_t child_cv; static unsigned child_ticker; +static unsigned gotint; +static unsigned dstarts; /*--------------------------------------------------------------------*/ static void * child_listener(void *arg) { - FILE *f; + int i; char buf[BUFSIZ]; (void)arg; - f = fdopen(child_fds[0], "r"); - assert(f != NULL); - while (fgets(buf, sizeof buf, f)) { + while (1) { + i = read(child_fds[0], buf, sizeof buf - 1); + if (i <= 0) + break; + buf[i] = '\0'; printf("Child said: %s", buf); } return (NULL); @@ -77,7 +82,6 @@ start_child(void) if (i < 0) errx(1, "Could not fork child"); if (i == 0) { - AZ(pthread_single_np()); /* Redirect stdin/out/err */ AZ(close(0)); i = open("/dev/null", O_RDONLY); @@ -90,6 +94,7 @@ start_child(void) AZ(close(heritage.fds[0])); AZ(close(heritage.fds[3])); + setproctitle("Varnish-Chld"); child_main(); exit (1); @@ -98,13 +103,18 @@ start_child(void) printf("start child pid %d\n", i); AZ(close(child_fds[1])); + child_fds[1] = -1; + mgt_cli_start_child(heritage.fds[0], heritage.fds[3]); AZ(close(heritage.fds[1])); + heritage.fds[1] = -1; AZ(close(heritage.fds[2])); - mgt_cli_start_child(heritage.fds[0], heritage.fds[3]); + heritage.fds[2] = -1; child_pid = i; AZ(pthread_create(&child_listen_thread, NULL, child_listener, NULL)); + AZ(pthread_detach(child_listen_thread)); AZ(pthread_create(&child_poker_thread, NULL, child_poker, NULL)); + AZ(pthread_detach(child_poker_thread)); } /*--------------------------------------------------------------------*/ @@ -112,13 +122,45 @@ start_child(void) static void stop_child(void) { + int i; + + assert(child_pid != -1); + + printf("Stop child\n"); + AZ(pthread_cancel(child_poker_thread)); + mgt_cli_stop_child(); + + /* We tell the child to die gracefully by closing the CLI */ + AZ(close(heritage.fds[0])); + heritage.fds[0] = -1; + AZ(close(heritage.fds[3])); + heritage.fds[3] = -1; + + /* + * Give it one second to die, then wack it hard + * then another second and then we get real angry + */ + for (i = 0; i < 30; i++) { + printf("Waiting %d %d\n",i, child_pid); + if (child_pid == -2) + break; + if (i == 10) { + printf("Giving cacher SIGINT\n"); + kill(child_pid, SIGINT); + } + if (i == 20) { + printf("Giving cacher SIGKILL\n"); + kill(child_pid, SIGKILL); + } + usleep(100000); + } - exit(2); - /* kill child, if relevant */ - /* join child_listen_thread */ - /* join child_poker_thread */ - /* close heritage.fds */ - /* close child_fds */ + assert(child_pid == -2); + + AZ(close(child_fds[0])); + child_fds[0] = -1; + child_pid = -1; + printf("Child stopped\n"); } /*--------------------------------------------------------------------*/ @@ -134,13 +176,29 @@ mgt_sigchld(int arg) if (r == child_pid) { printf("Cache child died pid=%d status=0x%x\n", r, status); - child_pid = -1; + child_pid = -2; } else { printf("Unknown child died pid=%d status=0x%x\n", r, status); } } +/*--------------------------------------------------------------------*/ + +static void +mgt_sigint(int arg) +{ + + (void)arg; + if (getpid() != mgr_pid) { + printf("Got SIGINT\n"); + exit (2); + } + printf("Manager got SIGINT\n"); + gotint = 1; + child_should_run = 0; +} + /*-------------------------------------------------------------------- * This thread is the master thread in the management process. * The relatively simple task is to start and stop the child process @@ -152,29 +210,49 @@ mgt_run(int dflag) { struct timespec to; struct sigaction sac; - int i, dstarts = 0; + int i; + + mgr_pid = getpid(); -#if 1 if (dflag) mgt_cli_setup(0, 1, 1); -#else - dflag = 0; -#endif sac.sa_handler = mgt_sigchld; - sac.sa_flags = SA_NOCLDSTOP; + sac.sa_flags = SA_RESTART | SA_NOCLDSTOP; AZ(sigaction(SIGCHLD, &sac, NULL)); + + sac.sa_handler = mgt_sigint; + sac.sa_flags = SA_RESTART; + AZ(sigaction(SIGINT, &sac, NULL)); + AZ(sigaction(SIGTERM, &sac, NULL)); + + setproctitle("Varnish-Mgr"); + + sac.sa_handler = SIG_IGN; + sac.sa_flags = SA_RESTART; + AZ(sigaction(SIGPIPE, &sac, NULL)); + AZ(sigaction(SIGHUP, &sac, NULL)); + child_should_run = !dflag; AZ(pthread_cond_init(&child_cv, NULL)); AZ(pthread_mutex_init(&child_mtx, NULL)); while (1) { + if (child_should_run && child_pid == -2) + stop_child(); if (!child_should_run && child_pid != -1) stop_child(); - else if (child_should_run && child_pid == -1) { - if (dflag && dstarts) + if (gotint) { + printf("Manager died due to sigint\n"); + exit(2); + } + if (child_should_run && child_pid == -1) { + if (dflag && dstarts) { + printf( + "Manager not autostarting in debug mode\n"); exit(2); + } start_child(); dstarts = 1; } @@ -200,6 +278,7 @@ void mgt_start_child(void) { + dstarts = 0; child_should_run = 1; AZ(pthread_cond_signal(&child_cv)); }