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
----------------------------
#include <unistd.h>
#include <errno.h>
-static int pid_daemon;
+int pid_daemon;
static char lock_path[PATH_MAX];
static void
}
}
+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
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';
/* 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 */
/* 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);
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++) {
}
#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;
* 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;
unsigned int options;
unsigned long last_timeout_check_s;
+ int started_with_parent;
+
int fd_random;
int listen_service_modulo;
int listen_service_count;
#endif /* EXTERNAL_POLL */
-//#define LWS_NO_FORK
/*
* This demo server shows how to use libwebsockets for one or more
}
}
+#ifndef NO_DAEMONIZE
/*
* normally lock path would be /var/lock/lwsts or similar, to
* simplify getting started without having to take care about
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);
lwsl_err("Unable to fork service loop %d\n", n);
return 1;
}
+ if (n)
+ exit(0);
while (1) {