From 68be9af4550ecaefc8850cbf636e3836fbf18058 Mon Sep 17 00:00:00 2001 From: phk Date: Thu, 16 Mar 2006 10:48:50 +0000 Subject: [PATCH] Expand the empty shell a bit. Add CLI handler on stdin (for now, in production only if debug is specified). Implement help, verbos, ping and start. start forks the child process, sets up listeners on its stdout/stderr (where nothing should arrive in production). Add SIGCHLD handler to reap and restart the child. Add shell "main" for the child: Set up a CLI handler on the pipes passed as heritage. Add ping command and keepalive timeout. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@56 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- varnish-cache/bin/varnishd/Makefile.am | 9 +- varnish-cache/bin/varnishd/cache_main.c | 87 +++++++++ varnish-cache/bin/varnishd/heritage.h | 13 ++ varnish-cache/bin/varnishd/varnishd.c | 235 ++++++++++++++++++++++++ 4 files changed, 342 insertions(+), 2 deletions(-) create mode 100644 varnish-cache/bin/varnishd/cache_main.c create mode 100644 varnish-cache/bin/varnishd/heritage.h diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am index 4c8f6cf5..507e5c54 100644 --- a/varnish-cache/bin/varnishd/Makefile.am +++ b/varnish-cache/bin/varnishd/Makefile.am @@ -1,10 +1,15 @@ # $Id$ -INCLUDES = -I$(top_srcdir)/include +INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/contrib/libevent bin_PROGRAMS = varnishd varnishd_SOURCES = \ + cache_main.c \ + cli_event.c \ varnishd.c -#varnishd_LDADD = $(top_builddir)/lib/libvarnish/libvarnish.la +varnishd_LDADD = \ + $(top_builddir)/lib/libvarnish/libvarnish.la \ + $(top_builddir)/lib/libsbuf/libsbuf.la \ + $(top_builddir)/contrib/libevent/libevent.la diff --git a/varnish-cache/bin/varnishd/cache_main.c b/varnish-cache/bin/varnishd/cache_main.c new file mode 100644 index 00000000..0aafb320 --- /dev/null +++ b/varnish-cache/bin/varnishd/cache_main.c @@ -0,0 +1,87 @@ +/* + * $Id$ + */ + +#include +#include +#include + +#include + +#include +#include + +#include "heritage.h" + +static struct event ev_keepalive; + +/*--------------------------------------------------------------------*/ + +static void +timer_keepalive(int a, short b, void *c) +{ + + printf("%s(%d, %d, %p)\n", __func__, a, b, c); + printf("Heeellloooo ? Ohh bother...\n"); + exit (1); +} + +static void +arm_keepalive(void) +{ + struct timeval tv; + + tv.tv_sec = 5; + tv.tv_usec = 0; + + evtimer_del(&ev_keepalive); + evtimer_add(&ev_keepalive, &tv); +} + +/*--------------------------------------------------------------------*/ + +static void +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]); + time(&t); + cli_out(cli, "PONG %ld\n", t); +} + +/*--------------------------------------------------------------------*/ + +static struct cli_proto cli_proto[] = { + { CLI_PING }, + { NULL } +}; + +void +child_main(void) +{ + struct event_base *eb; + struct cli *cli; + int i; + + setbuf(stdout, NULL); + setbuf(stderr, NULL); + printf("Child starts\n"); + + eb = event_init(); + assert(eb != NULL); + + cli = cli_setup(heritage.fds[0], heritage.fds[1], 0, cli_proto); + + evtimer_set(&ev_keepalive, timer_keepalive, NULL); + arm_keepalive(); + + i = event_dispatch(); + if (i != 0) + printf("event_dispatch() = %d\n", i); + + printf("Child dies\n"); +} + diff --git a/varnish-cache/bin/varnishd/heritage.h b/varnish-cache/bin/varnishd/heritage.h new file mode 100644 index 00000000..aaf0e713 --- /dev/null +++ b/varnish-cache/bin/varnishd/heritage.h @@ -0,0 +1,13 @@ +/* + * $Id$ + * + * This file contains the heritage passed when mgt forks cache + */ + +struct heritage { + int fds[2]; +}; + +extern struct heritage heritage; + +void child_main(void); diff --git a/varnish-cache/bin/varnishd/varnishd.c b/varnish-cache/bin/varnishd/varnishd.c index ffa9ebae..2d81c1f1 100644 --- a/varnish-cache/bin/varnishd/varnishd.c +++ b/varnish-cache/bin/varnishd/varnishd.c @@ -3,9 +3,239 @@ */ #include +#include +#include #include #include #include +#include +#include + +#include + +#include +#include + +#include +#include +#include + +#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__, bev, arg); + exit (2); +} + +static void +std_excb(struct bufferevent *bev, short what, void *arg) +{ + + printf("%s(%p, %d, %p)\n", __func__, bev, what, arg); + exit (2); +} + + + +/*--------------------------------------------------------------------*/ + +static void +start_child(void) +{ + 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); +} + +/*--------------------------------------------------------------------*/ + +static void +sig_chld(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(child_fds[0]); + close(child_fds[1]); + + if (desired == H_START) + start_child(); +} + +/*--------------------------------------------------------------------*/ + +static void +cli_func_server_start(struct cli *cli, char **av __unused, void *priv __unused) +{ + + if (desired != H_START) { + desired = H_START; + start_child(); + } +} + +/*--------------------------------------------------------------------*/ + +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 + } +} + +/*--------------------------------------------------------------------*/ + +static void +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) +{ + time_t t; + + if (av[2] != NULL) { + cli_out(cli, "Got your %s\n", av[2]); + } + time(&t); + cli_out(cli, "PONG %ld\n", t); +} + +/*--------------------------------------------------------------------*/ + +static struct cli_proto cli_proto[] = { + /* URL manipulation */ + { CLI_URL_QUERY }, + { CLI_URL_PURGE }, + { CLI_URL_STATUS }, + { CLI_CONFIG_LOAD }, + { CLI_CONFIG_INLINE }, + { CLI_CONFIG_UNLOAD }, + { CLI_CONFIG_LIST }, + { CLI_CONFIG_USE }, + { CLI_SERVER_FREEZE }, + { CLI_SERVER_THAW }, + { CLI_SERVER_SUSPEND }, + { CLI_SERVER_RESUME }, + { CLI_SERVER_STOP, cli_func_server_stop, NULL }, + { CLI_SERVER_START, cli_func_server_start, NULL }, + { CLI_SERVER_RESTART }, + { CLI_PING, cli_func_ping, NULL }, + { CLI_STATS }, + { CLI_ZERO }, + { CLI_HELP, cli_func_help, cli_proto }, + { CLI_VERBOSE, cli_func_verbose, NULL }, + { CLI_EXIT }, + { CLI_QUIT }, + { CLI_BYE }, + { NULL } +}; + +static void +testme(void) +{ + struct event e_sigchld; + struct cli *cli; + int i; + + eb = event_init(); + assert(eb != NULL); + + cli = cli_setup(0, 1, 1, cli_proto); + + signal_set(&e_sigchld, SIGCHLD, sig_chld, NULL); + signal_add(&e_sigchld, NULL); + + i = event_dispatch(); + if (i != 0) + printf("event_dispatch() = %d\n", i); + +} + +/*--------------------------------------------------------------------*/ static void usage(void) @@ -26,6 +256,8 @@ usage(void) exit(1); } +/*--------------------------------------------------------------------*/ + int main(int argc, char *argv[]) { @@ -51,5 +283,8 @@ main(int argc, char *argv[]) if (argc != 0) usage(); + testme(); + + exit(0); } -- 2.39.5