From 53afa71a3be97cb38f81e9d33484781c9453bc49 Mon Sep 17 00:00:00 2001 From: phk Date: Fri, 17 Mar 2006 10:03:05 +0000 Subject: [PATCH] Add multiplexing for the mgt->child cli connection and get ping/pong working across it. The management process will now keep the child process watchdog from expiring. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@58 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/Makefile.am | 1 + varnish-cache/bin/varnishd/cache_main.c | 10 +- varnish-cache/bin/varnishd/cli_event.c | 2 +- varnish-cache/bin/varnishd/heritage.h | 2 +- varnish-cache/bin/varnishd/mgt.h | 12 + varnish-cache/bin/varnishd/mgt_child.c | 291 ++++++++++++++++++++++++ varnish-cache/bin/varnishd/varnishd.c | 124 ++-------- 7 files changed, 326 insertions(+), 116 deletions(-) create mode 100644 varnish-cache/bin/varnishd/mgt.h create mode 100644 varnish-cache/bin/varnishd/mgt_child.c diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 507e5c54..32d8553c 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -7,6 +7,7 @@ bin_PROGRAMS = varnishd varnishd_SOURCES = \ cache_main.c \ cli_event.c \ + mgt_child.c \ varnishd.c varnishd_LDADD = \ diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c index 6cb3c350..74d2b78c 100644 --- a/varnish-cache/bin/varnishd/cache_main.c +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -33,7 +33,7 @@ arm_keepalive(void) { struct timeval tv; - tv.tv_sec = 5; + tv.tv_sec = 30; tv.tv_usec = 0; evtimer_del(&ev_keepalive); @@ -48,8 +48,10 @@ cli_func_ping(struct cli *cli, char **av, void *priv __unused) time_t t; arm_keepalive(); - if (av[2] != NULL) - cli_out(cli, "Got your %s\n", av[2]); + if (av[2] != NULL) { + /* XXX: check clock skew is pointless here */ + printf("Got your ping %s\n", av[2]); + } time(&t); cli_out(cli, "PONG %ld\n", t); } @@ -75,7 +77,7 @@ child_main(void) eb = event_init(); assert(eb != NULL); - cli = cli_setup(heritage.fds[0], heritage.fds[1], 0, cli_proto); + cli = cli_setup(heritage.fds[2], heritage.fds[1], 0, cli_proto); evtimer_set(&ev_keepalive, timer_keepalive, NULL); arm_keepalive(); diff --git a/varnish-cache/bin/varnishd/cli_event.c b/varnish-cache/bin/varnishd/cli_event.c index 8621efe4..70c83a8d 100644 --- a/varnish-cache/bin/varnishd/cli_event.c +++ b/varnish-cache/bin/varnishd/cli_event.c @@ -108,7 +108,7 @@ wrcb(struct bufferevent *bev, void *arg) static void excb(struct bufferevent *bev, short what, void *arg) { - printf("Exception\n"); + printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg); } struct cli * diff --git a/varnish-cache/bin/varnishd/heritage.h b/varnish-cache/bin/varnishd/heritage.h index aaf0e713..c1b8e78b 100644 --- a/varnish-cache/bin/varnishd/heritage.h +++ b/varnish-cache/bin/varnishd/heritage.h @@ -5,7 +5,7 @@ */ struct heritage { - int fds[2]; + int fds[4]; }; extern struct heritage heritage; diff --git a/varnish-cache/bin/varnishd/mgt.h b/varnish-cache/bin/varnishd/mgt.h new file mode 100644 index 00000000..b903e032 --- /dev/null +++ b/varnish-cache/bin/varnishd/mgt.h @@ -0,0 +1,12 @@ +/* + * $Id$ + */ + +extern struct event_base *eb; + +void mgt_child_start(void); +void mgt_child_stop(void); +void mgt_sigchld(int, short, void *); + +typedef void mgt_ccb_f(unsigned, const char *, void *); +void mgt_child_request(mgt_ccb_f *, void *, const char *fmt, ...); diff --git a/varnish-cache/bin/varnishd/mgt_child.c b/varnish-cache/bin/varnishd/mgt_child.c new file mode 100644 index 00000000..1e2251eb --- /dev/null +++ b/varnish-cache/bin/varnishd/mgt_child.c @@ -0,0 +1,291 @@ +/* + * $Id$ + * + * The mechanics of handling the child process + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include +#include + +#include "heritage.h" +#include "mgt.h" + +/*--------------------------------------------------------------------*/ + +static enum { + H_STOP = 0, + H_START +} desired; + +static pid_t child_pid; +static int child_fds[2]; + +static struct bufferevent *child_std; +static struct bufferevent *child_cli0, *child_cli1; + +static struct event ev_child_pingpong; + +struct creq { + TAILQ_ENTRY(creq) list; + char *req; + mgt_ccb_f *func; + void *priv; +}; + +static TAILQ_HEAD(,creq) creqhead = TAILQ_HEAD_INITIALIZER(creqhead); + +/*-------------------------------------------------------------------- + * Handle stdout+stderr from the child. + */ + +static void +std_rdcb(struct bufferevent *bev, void *arg) +{ + const char *p; + + p = evbuffer_readline(bev->input); + if (p == NULL) + return; + printf("Child said <%s>\n", p); +} + +static void +std_wrcb(struct bufferevent *bev, void *arg) +{ + + printf("%s(%p, %p)\n", __func__, (void*)bev, arg); + exit (2); +} + +static void +std_excb(struct bufferevent *bev, short what, void *arg) +{ + + printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg); + exit (2); +} + +/*-------------------------------------------------------------------- + * Multiplex requests/answers to the child + */ + +static void +send_req(void) +{ + struct creq *cr; + + cr = TAILQ_FIRST(&creqhead); + if (cr == NULL) + return; + printf("Send Request <%s>\n", cr->req); + evbuffer_add_printf(child_cli1->output, "%s\n", cr->req); + bufferevent_enable(child_cli1, EV_WRITE); +} + +void +mgt_child_request(mgt_ccb_f *func, void *priv, const char *fmt, ...) +{ + struct creq *cr; + va_list ap; + int i; + + cr = calloc(sizeof *cr, 1); + assert(cr != NULL); + cr->func = func; + cr->priv = priv; + va_start(ap, fmt); + vasprintf(&cr->req, fmt, ap); + va_end(ap); + i = TAILQ_EMPTY(&creqhead); + TAILQ_INSERT_TAIL(&creqhead, cr, list); + if (i) + send_req(); +} + +static void +cli_rdcb(struct bufferevent *bev, void *arg) +{ + const char *p; + char **av; + struct creq *cr; + + p = evbuffer_readline(bev->input); + if (p == NULL) + return; + cr = TAILQ_FIRST(&creqhead); + assert(cr != NULL); + av = ParseArgv(p, 0); + if (av[0] != NULL) + cr->func(CLIS_SYNTAX, av[0], cr->priv); + else + cr->func(strtoul(av[1], NULL, 0), av[2], cr->priv); + FreeArgv(av); + TAILQ_REMOVE(&creqhead, cr, list); + free(cr->req); + free(cr); + send_req(); +} + +static void +cli_wrcb(struct bufferevent *bev __unused, void *arg __unused) +{ + +} + +static void +cli_excb(struct bufferevent *bev, short what, void *arg) +{ + + printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg); + exit (2); +} + +/*--------------------------------------------------------------------*/ + +static void +child_pingpong_ccb(unsigned u, const char *r, void *priv) +{ + printf("%s(%u, \"%s\", %p)\n", __func__, u, r, priv); + /* XXX: reset keepalive timer */ +} + + +static void +child_pingpong(int a, short b, void *c) +{ + time_t t; + struct timeval tv; + + printf("%s(%d, %d, %p)\n", __func__, a, b, c); + time(&t); + mgt_child_request(child_pingpong_ccb, NULL, "ping %ld", t); + if (1) { + tv.tv_sec = 3; + tv.tv_usec = 0; + evtimer_del(&ev_child_pingpong); + evtimer_add(&ev_child_pingpong, &tv); + } +} + + +/*--------------------------------------------------------------------*/ + +static void +start_child(void) +{ + int i; + + assert(pipe(&heritage.fds[0]) == 0); + assert(pipe(&heritage.fds[2]) == 0); + assert(pipe(child_fds) == 0); + i = fork(); + if (i < 0) + errx(1, "Could not fork child"); + if (i == 0) { + /* XXX: close fds */ + /* XXX: (re)set signals */ + + /* Redirect stdin/out/err */ + close(0); + i = open("/dev/null", O_RDONLY); + assert(i == 0); + close(child_fds[0]); + dup2(child_fds[1], 1); + dup2(child_fds[1], 2); + close(child_fds[1]); + + child_main(); + + exit (1); + } + child_pid = i; + printf("start child pid %d\n", i); + + /* + * We do not close the unused ends of the pipes here to avoid + * doing SIGPIPE handling. + */ + child_std = bufferevent_new(child_fds[0], + std_rdcb, std_wrcb, std_excb, NULL); + assert(child_std != NULL); + bufferevent_enable(child_std, EV_READ); + child_cli0 = bufferevent_new(heritage.fds[0], + cli_rdcb, cli_wrcb, cli_excb, NULL); + assert(child_cli0 != NULL); + bufferevent_enable(child_cli0, EV_READ); + child_cli1 = bufferevent_new(heritage.fds[3], + cli_rdcb, cli_wrcb, cli_excb, NULL); + assert(child_cli1 != NULL); + + evtimer_set(&ev_child_pingpong, child_pingpong, NULL); + child_pingpong(0, 0, NULL); +} + + +/*--------------------------------------------------------------------*/ + +void +mgt_child_start(void) +{ + + if (desired == H_START) + return; + desired = H_START; + start_child(); +} + +/*--------------------------------------------------------------------*/ + +void +mgt_child_stop(void) +{ + + if (desired == H_STOP) + return; + desired = H_STOP; +} + +/*--------------------------------------------------------------------*/ + +void +mgt_sigchld(int a, short b, void *c) +{ + pid_t p; + int status; + + printf("sig_chld(%d, %d, %p)\n", a, b, c); + + p = wait4(-1, &status, WNOHANG, NULL); + printf("pid = %d status = 0x%x\n", p, status); + assert(p == child_pid); + + bufferevent_free(child_std); /* XXX: is this enough ? */ + child_std = NULL; + + close(heritage.fds[0]); + close(heritage.fds[1]); + close(heritage.fds[2]); + close(heritage.fds[3]); + close(child_fds[0]); + close(child_fds[1]); + + if (desired == H_START) + start_child(); +} diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index 6a688668..422337e5 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -1,5 +1,7 @@ /* * $Id$ + * + * The management process and CLI handling */ #include @@ -22,121 +24,30 @@ #include #include +#include "mgt.h" #include "heritage.h" #include "cli_event.h" /*--------------------------------------------------------------------*/ -static enum { - H_STOP = 0, - H_START -} desired; -static pid_t child_pid; -static int child_fds[2]; - struct heritage heritage; - -static struct event_base *eb; - -static struct bufferevent *child_std; - -/*--------------------------------------------------------------------*/ - -static void -std_rdcb(struct bufferevent *bev, void *arg) -{ - const char *p; - - p = evbuffer_readline(bev->input); - if (p == NULL) - return; - printf("Child said <%s>\n", p); -} - -static void -std_wrcb(struct bufferevent *bev, void *arg) -{ - - printf("%s(%p, %p)\n", __func__, (void*)bev, arg); - exit (2); -} - -static void -std_excb(struct bufferevent *bev, short what, void *arg) -{ - - printf("%s(%p, %d, %p)\n", __func__, (void*)bev, what, arg); - exit (2); -} - - +struct event_base *eb; /*--------------------------------------------------------------------*/ -static void -start_child(void) +void +xxx_ccb(unsigned u, const char *r, void *priv) { - int i; - - assert(pipe(heritage.fds) == 0); - assert(pipe(child_fds) == 0); - i = fork(); - if (i < 0) - errx(1, "Could not fork child"); - if (i == 0) { - /* XXX: close fds */ - /* XXX: (re)set signals */ - - /* Redirect stdin/out/err */ - close(0); - i = open("/dev/null", O_RDONLY); - assert(i == 0); - close(child_fds[0]); - dup2(child_fds[1], 1); - dup2(child_fds[1], 2); - close(child_fds[1]); - - child_main(); - - exit (1); - } - child_pid = i; - printf("start child pid %d\n", i); - - /* - * We do not close the unused ends of the pipes here to avoid - * doing SIGPIPE handling. - */ - child_std = bufferevent_new(child_fds[0], - std_rdcb, std_wrcb, std_excb, NULL); - assert(child_std != NULL); - bufferevent_enable(child_std, EV_READ); + printf("%s(%u, %s, %p)\n", __func__, u, r, priv); } /*--------------------------------------------------------------------*/ static void -sig_chld(int a, short b, void *c) +cli_func_url_query(struct cli *cli, char **av __unused, void *priv __unused) { - pid_t p; - int status; - - printf("sig_chld(%d, %d, %p)\n", a, b, c); - - p = wait4(-1, &status, WNOHANG, NULL); - printf("pid = %d status = 0x%x\n", p, status); - assert(p == child_pid); - - bufferevent_free(child_std); /* XXX: is this enough ? */ - child_std = NULL; - close(heritage.fds[0]); - close(heritage.fds[1]); - close(child_fds[0]); - close(child_fds[1]); - - if (desired == H_START) - start_child(); + mgt_child_request(xxx_ccb, NULL, "url.query %s", av[2]); } /*--------------------------------------------------------------------*/ @@ -145,10 +56,7 @@ static void cli_func_server_start(struct cli *cli, char **av __unused, void *priv __unused) { - if (desired != H_START) { - desired = H_START; - start_child(); - } + mgt_child_start(); } /*--------------------------------------------------------------------*/ @@ -157,12 +65,7 @@ static void cli_func_server_stop(struct cli *cli, char **av __unused, void *priv __unused) { - if (desired != H_STOP) { - desired = H_STOP; -#if 0 - stop_child(); -#endif - } + mgt_child_stop(); } /*--------------------------------------------------------------------*/ @@ -174,6 +77,7 @@ cli_func_verbose(struct cli *cli, char **av __unused, void *priv) cli->verbose = !cli->verbose; } + static void cli_func_ping(struct cli *cli, char **av, void *priv __unused) { @@ -190,7 +94,7 @@ cli_func_ping(struct cli *cli, char **av, void *priv __unused) static struct cli_proto cli_proto[] = { /* URL manipulation */ - { CLI_URL_QUERY }, + { CLI_URL_QUERY, cli_func_url_query, NULL }, { CLI_URL_PURGE }, { CLI_URL_STATUS }, { CLI_CONFIG_LOAD }, @@ -228,7 +132,7 @@ testme(void) cli = cli_setup(0, 1, 1, cli_proto); - signal_set(&e_sigchld, SIGCHLD, sig_chld, NULL); + signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL); signal_add(&e_sigchld, NULL); i = event_dispatch(); -- 2.39.5