]> err.no Git - varnish/commitdiff
Don my plumbers outfit and twist a lot of pipes into shape:
authorphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 2 Aug 2006 13:28:14 +0000 (13:28 +0000)
committerphk <phk@d4fa192b-c00b-0410-8231-f00ffab90ce4>
Wed, 2 Aug 2006 13:28:14 +0000 (13:28 +0000)
When -d(ebug) is specified we fork before calling daemon.

The parent process becomes a miniature cat(1) program which connects
stdin/stdout with the management process stdin/stdout.

It also knows that SIGINT should be passed on to the management process
in order to make it DTRT.

Any other cause of death for this "debugger" process will (once I
teach the CLI about it) not affect the running varnish and therefore
it will be possible to start varnish in debugging mode, tweak things
a bit and CTRL-D and leave it running in the properly daemon(3)'ed
background.

The reason for this rather complicated bit of pipework is that we
can not call daemon(3) once we have started any threads (only the
calling thread survives) and we would loose our parent relationship
to the cache process also.

git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@604 d4fa192b-c00b-0410-8231-f00ffab90ce4

varnish-cache/bin/varnishd/mgt_child.c
varnish-cache/bin/varnishd/varnishd.c

index b3ca735023493d7a148f0de42c0d66894107412d..7ed370a1ae1e3748e7d1eb7440958b798328d60b 100644 (file)
@@ -226,29 +226,31 @@ start_child(void)
        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);
+               AZ(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]);
+               assert(dup2(child_fds[1], 1) == 1);
+               assert(dup2(child_fds[1], 2) == 2);
+               AZ(close(child_fds[0]));
+               AZ(close(child_fds[1]));
+
+               AZ(close(heritage.fds[0]));
+               AZ(close(heritage.fds[3]));
 
                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.
-        */
+       AZ(close(child_fds[1]));
+
+       AZ(close(heritage.fds[1]));
+       AZ(close(heritage.fds[2]));
+
        child_std = bufferevent_new(child_fds[0],
            std_rdcb, std_wrcb, std_excb, NULL);
        assert(child_std != NULL);
index 44bb1cdfc2085c168e078d627b06574d837915ca..54300b03d6f5637143bdfe82ed31e110ad683a5e 100644 (file)
@@ -11,6 +11,7 @@
 #include <limits.h>
 #include <signal.h>
 #include <stdarg.h>
+#include <poll.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <time.h>
@@ -18,8 +19,8 @@
 
 #include <sys/wait.h>
 
-#include <event.h>
-#include <sbuf.h>
+#include "event.h"
+#include "sbuf.h"
 
 #include <cli.h>
 #include <cli_priv.h>
@@ -328,29 +329,6 @@ static struct cli_proto cli_proto[] = {
        { NULL }
 };
 
-static void
-testme(void)
-{
-       struct event e_sigchld;
-       struct cli *cli;
-       int i;
-
-       mgt_eb = event_init();
-       assert(mgt_eb != NULL);
-
-       cli = cli_setup(mgt_eb, 0, 1, 1, cli_proto);
-
-       signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL);
-       AZ(event_base_set(mgt_eb, &e_sigchld));
-       AZ(signal_add(&e_sigchld, NULL));
-
-       mgt_child_start();
-
-       i = event_base_loop(mgt_eb, 0);
-       if (i != 0)
-               printf("event_dispatch() = %d\n", i);
-
-}
 
 /*--------------------------------------------------------------------*/
 
@@ -515,18 +493,107 @@ tackle_warg(const char *argv)
                heritage.wthread_timeout = uc;
 }
 
+/*--------------------------------------------------------------------
+ * When -d is specified we fork a third process which will relay
+ * keystrokes between the terminal and the CLI.  This allows us to
+ * detach from the process and have it daemonize properly (ie: it already
+ * did that long time ago).
+ * Doing the simple thing and calling daemon(3) when the user asks for
+ * it does not work, daemon(3) forks and all the threads are lost.
+ */
+
+static pid_t d_child;
+
+#include <err.h>
+
+static void
+DebugSigPass(int sig)
+{
+       int i;
+
+       i = kill(d_child, sig);
+       printf("sig %d i %d pid %d\n", sig, i, d_child);
+}
+
+static void
+DebugStunt(void)
+{
+       int pipes[2][2];
+       struct pollfd pfd[2];
+       char buf[BUFSIZ];
+       int i, j, k;
+       char *p;
+
+       AZ(pipe(pipes[0]));
+       AZ(pipe(pipes[1]));
+       d_child = fork();
+       if (!d_child) {
+               assert(dup2(pipes[0][0], 0) >= 0);
+               assert(dup2(pipes[1][1], 1) >= 0);
+               assert(dup2(pipes[1][1], 2) >= 0);
+               AZ(close(pipes[0][0]));
+               AZ(close(pipes[0][1]));
+               AZ(close(pipes[1][0]));
+               AZ(close(pipes[1][1]));
+               return;
+       }
+       AZ(close(pipes[0][0]));
+       assert(dup2(pipes[0][1], 3) >= 0);
+       pipes[0][0] = 0;
+       pipes[0][1] = 3;
+
+       assert(dup2(pipes[1][0], 4) >= 0);
+       AZ(close(pipes[1][1]));
+       pipes[1][0] = 4;
+       pipes[1][1] = 1;
+
+       for (i = 5; i < 100; i++)
+               close(i);
+
+       pfd[0].fd = pipes[0][0];
+       pfd[0].events = POLLIN;
+       pfd[1].fd = pipes[1][0];
+       pfd[1].events = POLLIN;
+
+       signal(SIGINT, DebugSigPass);
+       i = read(pipes[1][0], buf, sizeof buf - 1);
+       buf[i] = '\0';
+       d_child = strtoul(buf, &p, 0);
+       assert(p != NULL);
+       printf("New Pid %d\n", d_child);
+       i = strlen(p);
+       j = write(pipes[1][1], p, i);
+       assert(j == i);
+
+       while (1) {
+               i = poll(pfd, 2, INFTIM);
+               for (k = 0; k < 2; k++) {
+                       if (pfd[k].revents) {
+                               j = read(pipes[k][0], buf, sizeof buf);
+                               if (j == 0)
+                                       exit (0);
+                               if (j > 0) {
+                                       i = write(pipes[k][1], buf, j);
+                                       if (i != j)
+                                               err(1, "i = %d j = %d\n", i, j);
+                               }
+                       }
+               }
+       }
+}
+
+
 /*--------------------------------------------------------------------*/
 
 /* for development purposes */
 #include <printf.h>
-#include <err.h>
 
 int
 main(int argc, char *argv[])
 {
        int o;
        const char *portnumber = "8080";
-       unsigned dflag = 1;     /* XXX: debug=on for now */
+       unsigned dflag = 0;
        const char *bflag = NULL;
        const char *fflag = NULL;
        const char *sflag = "file";
@@ -613,7 +680,34 @@ main(int argc, char *argv[])
 
        VSL_MgtInit(SHMLOG_FILENAME, 8*1024*1024);
 
-       testme();
+       if (dflag)
+               DebugStunt();
+       daemon(0, dflag);
+       if (dflag)
+               printf("%d\n%d\n%d\n", getpid(), getsid(0), getpgrp());
+
+       {
+       struct event e_sigchld;
+       struct cli *cli;
+       int i;
+
+       mgt_eb = event_init();
+       assert(mgt_eb != NULL);
+
+       if (dflag)
+               cli = cli_setup(mgt_eb, 0, 1, 1, cli_proto);
+
+       signal_set(&e_sigchld, SIGCHLD, mgt_sigchld, NULL);
+       AZ(event_base_set(mgt_eb, &e_sigchld));
+       AZ(signal_add(&e_sigchld, NULL));
+
+       mgt_child_start();
+
+       i = event_base_loop(mgt_eb, 0);
+       if (i != 0)
+               printf("event_dispatch() = %d\n", i);
+
+       }
 
        exit(0);
 }