make use of lock file

Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
Andy Green 2013-01-19 13:56:10 +08:00
parent 0bf3ef605d
commit 24cba92c7e
5 changed files with 83 additions and 7 deletions

View file

@ -177,6 +177,29 @@ Incrementing numbers should appear in the browser display.
By default the test server logs to both stderr and syslog. 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 Using SSL on the server side
---------------------------- ----------------------------

View file

@ -21,7 +21,7 @@
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
static int pid_daemon; int pid_daemon;
static char lock_path[PATH_MAX]; static char lock_path[PATH_MAX];
static void 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 * You just need to call this from your main(), when it
* returns you are all set "in the background" decoupled * returns you are all set "in the background" decoupled
@ -76,11 +84,31 @@ int
lws_daemonize(const char *_lock_path) lws_daemonize(const char *_lock_path)
{ {
pid_t sid, parent; pid_t sid, parent;
int fd;
char buf[10];
int n, ret;
struct sigaction act;
/* already a daemon */ /* already a daemon */
if (getppid() == 1) if (getppid() == 1)
return (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); strncpy(lock_path, _lock_path, sizeof lock_path);
lock_path[sizeof(lock_path) - 1] = '\0'; 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 */ /* At this point we are executing as the child process */
parent = getppid(); parent = getppid();
pid_daemon = getpid();
/* Cancel certain signals */ /* Cancel certain signals */
signal(SIGCHLD, SIG_DFL); /* A child process dies */ 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 */ /* Tell the parent process that we are A-okay */
kill(parent, SIGUSR1); 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 to continue what is now "the daemon" */
return (0); return (0);

View file

@ -703,6 +703,10 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
if (context->last_timeout_check_s != tv.tv_sec) { if (context->last_timeout_check_s != tv.tv_sec) {
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 */ /* global timeout check once per second */
for (n = 0; n < context->fds_count; n++) { for (n = 0; n < context->fds_count; n++) {
@ -1443,12 +1447,17 @@ libwebsocket_create_context(int port, const char *interf,
} }
#endif #endif
context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context)); context = (struct libwebsocket_context *) malloc(sizeof(struct libwebsocket_context));
if (!context) { if (!context) {
lwsl_err("No memory for websocket context\n"); lwsl_err("No memory for websocket context\n");
return NULL; 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->protocols = protocols;
context->listen_port = port; context->listen_port = port;
context->http_proxy_port = 0; 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. * solaris, could remember ppid right after fork and wait for it to change.
*/ */
if (getppid() == 1) /* if our parent went down, don't linger around */
break; if (context->started_with_parent && kill(context->started_with_parent, 0) < 0)
kill(getpid(), SIGTERM);
if (getppid() == 1)
break;
//#endif //#endif
} }
return 1; return 1;

View file

@ -257,6 +257,8 @@ struct libwebsocket_context {
unsigned int options; unsigned int options;
unsigned long last_timeout_check_s; unsigned long last_timeout_check_s;
int started_with_parent;
int fd_random; int fd_random;
int listen_service_modulo; int listen_service_modulo;
int listen_service_count; int listen_service_count;

View file

@ -43,7 +43,6 @@ int count_pollfds;
#endif /* EXTERNAL_POLL */ #endif /* EXTERNAL_POLL */
//#define LWS_NO_FORK
/* /*
* This demo server shows how to use libwebsockets for one or more * 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 * normally lock path would be /var/lock/lwsts or similar, to
* simplify getting started without having to take care about * 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"); fprintf(stderr, "Failed to daemonize\n");
return 1; return 1;
} }
#endif
/* we will only try to log things according to our debug_level */ /* we will only try to log things according to our debug_level */
setlogmask(LOG_UPTO (LOG_DEBUG)); setlogmask(LOG_UPTO (LOG_DEBUG));
openlog("lwsts", syslog_options, LOG_DAEMON); 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); lwsl_err("Unable to fork service loop %d\n", n);
return 1; return 1;
} }
if (n)
exit(0);
while (1) { while (1) {