make use of lock file 46/2946/1
authorAndy Green <andy.green@linaro.org>
Sat, 19 Jan 2013 05:56:10 +0000 (13:56 +0800)
committerKevron Rees <kevron_m_rees@linux.intel.com>
Thu, 7 Mar 2013 21:01:27 +0000 (13:01 -0800)
Signed-off-by: Andy Green <andy.green@linaro.org>
README-test-server
lib/daemonize.c
lib/libwebsockets.c
lib/private-libwebsockets.h
test-server/test-server.c

index 1091c53..dd4a932 100644 (file)
@@ -177,6 +177,29 @@ Incrementing numbers should appear in the browser display.
 
 By default the test server logs to both stderr and syslog.
 
+
+Running test server as a Daemon
+-------------------------------
+
+You can use the -D option on the test server to have it fork into the
+background and return immediately.  In this daemonized mode all stderr is
+disabled and logging goes only to syslog, eg, /var/log/messages or similar.
+
+The server maintains a lockfile at /tmp/.lwsts-lock that contains the pid
+of the master process, and deletes this file when the master process
+terminates.
+
+To stop the daemon, do
+
+  kill `cat /tmp/.lwsts-lock`
+
+If it finds a stale lock (the pid mentioned in the file does not exist
+any more) it will delete the lock and create a new one during startup.
+
+If the lock is valid, the daemon will exit with a note on stderr that
+it was already running.s
+
+
 Using SSL on the server side
 ----------------------------
 
index 4add03d..9738fbd 100644 (file)
@@ -21,7 +21,7 @@
 #include <unistd.h>
 #include <errno.h>
 
-static int pid_daemon;
+int pid_daemon;
 static char lock_path[PATH_MAX];
 
 static void
@@ -64,6 +64,14 @@ child_handler(int signum)
        }
 }
 
+static void lws_daemon_closing(int sigact)
+{
+       if (getpid() == pid_daemon)
+               unlink(lock_path);
+
+       kill(getpid(), SIGKILL);
+}
+
 /*
  * You just need to call this from your main(), when it
  * returns you are all set "in the background" decoupled
@@ -76,11 +84,31 @@ int
 lws_daemonize(const char *_lock_path)
 {
        pid_t sid, parent;
+       int fd;
+       char buf[10];
+       int n, ret;
+       struct sigaction act;
 
        /* already a daemon */
        if (getppid() == 1)
                return (1);
 
+       fd = open(_lock_path, O_RDONLY);
+       if (fd > 0) {
+               n = read(fd, buf, sizeof buf);
+               close(fd);
+               if (n) {
+                       n = atoi(buf);
+                       ret = kill(n, 0);
+                       if (ret >= 0) {
+                               fprintf(stderr, "Daemon already running from pid %d, aborting\n", n);
+                               exit(1);
+                       }
+                       fprintf(stderr, "Removing stale lock file %s from dead pid %d\n", _lock_path, n);
+                       unlink(lock_path);
+               }
+       }
+
        strncpy(lock_path, _lock_path, sizeof lock_path);
        lock_path[sizeof(lock_path) - 1] = '\0';
 
@@ -114,6 +142,7 @@ lws_daemonize(const char *_lock_path)
 
        /* At this point we are executing as the child process */
        parent = getppid();
+       pid_daemon = getpid();
 
        /* Cancel certain signals */
        signal(SIGCHLD, SIG_DFL); /* A child process dies */
@@ -161,6 +190,13 @@ lws_daemonize(const char *_lock_path)
        /* Tell the parent process that we are A-okay */
        kill(parent, SIGUSR1);
 
+       act.sa_handler = lws_daemon_closing;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = 0;
+       act.sa_restorer = NULL;
+       
+       sigaction(SIGTERM, &act, NULL);
+
        /* return to continue what is now "the daemon" */
 
        return (0);
index 1b62f92..6ae44c4 100644 (file)
@@ -703,6 +703,10 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
        if (context->last_timeout_check_s != tv.tv_sec) {
                context->last_timeout_check_s = tv.tv_sec;
 
+               /* if our parent went down, don't linger around */
+               if (context->started_with_parent && kill(context->started_with_parent, 0) < 0)
+                       kill(getpid(), SIGTERM);
+
                /* global timeout check once per second */
 
                for (n = 0; n < context->fds_count; n++) {
@@ -1443,12 +1447,17 @@ libwebsocket_create_context(int port, const char *interf,
        }
 #endif
 
-
        context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
        if (!context) {
                lwsl_err("No memory for websocket context\n");
                return NULL;
        }
+#ifndef NO_DAEMONIZE
+       extern int pid_daemon;
+       context->started_with_parent = pid_daemon;
+       lwsl_notice(" Started with daemon pid %d\n", pid_daemon);
+#endif
+
        context->protocols = protocols;
        context->listen_port = port;
        context->http_proxy_port = 0;
@@ -1975,10 +1984,14 @@ libwebsockets_fork_service_loop(struct libwebsocket_context *context)
  * solaris, could remember ppid right after fork and wait for it to change.
  */
 
-        if (getppid() == 1)
-            break;
+               /* if our parent went down, don't linger around */
+               if (context->started_with_parent && kill(context->started_with_parent, 0) < 0)
+                       kill(getpid(), SIGTERM);
+
+               if (getppid() == 1)
+                   break;
 //#endif
-    }
+       }
 
 
        return 1;
index ce30949..8f69cff 100644 (file)
@@ -257,6 +257,8 @@ struct libwebsocket_context {
        unsigned int options;
        unsigned long last_timeout_check_s;
 
+       int started_with_parent;
+
        int fd_random;
        int listen_service_modulo;
        int listen_service_count;
index 7ac0a9b..dc5a9cd 100644 (file)
@@ -43,7 +43,6 @@ int count_pollfds;
 
 #endif /* EXTERNAL_POLL */
 
-//#define LWS_NO_FORK
 
 /*
  * This demo server shows how to use libwebsockets for one or more
@@ -562,6 +561,7 @@ int main(int argc, char **argv)
                }
        }
 
+#ifndef NO_DAEMONIZE
        /* 
         * normally lock path would be /var/lock/lwsts or similar, to
         * simplify getting started without having to take care about
@@ -571,7 +571,7 @@ int main(int argc, char **argv)
                fprintf(stderr, "Failed to daemonize\n");
                return 1;
        }
-
+#endif
        /* we will only try to log things according to our debug_level */
        setlogmask(LOG_UPTO (LOG_DEBUG));
        openlog("lwsts", syslog_options, LOG_DAEMON);
@@ -685,6 +685,8 @@ int main(int argc, char **argv)
                lwsl_err("Unable to fork service loop %d\n", n);
                return 1;
        }
+       if (n)
+               exit(0);
 
        while (1) {