adds reconfig and shutdown handler to srvctrl srvctrl

Wed, 25 Jan 2017 11:50:19 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 25 Jan 2017 11:50:19 +0100
branch
srvctrl
changeset 158
77f4f0079428
parent 156
724e107983e9
child 166
c07122f66676

adds reconfig and shutdown handler to srvctrl

src/server/daemon/main.c file | annotate | diff | comparison | revisions
src/server/daemon/objs.mk file | annotate | diff | comparison | revisions
src/server/daemon/srvctrl.c file | annotate | diff | comparison | revisions
src/server/daemon/srvctrl.h file | annotate | diff | comparison | revisions
src/server/daemon/webserver.c file | annotate | diff | comparison | revisions
src/server/daemon/webserver.h file | annotate | diff | comparison | revisions
--- a/src/server/daemon/main.c	Tue Jan 24 22:48:14 2017 +0100
+++ b/src/server/daemon/main.c	Wed Jan 25 11:50:19 2017 +0100
@@ -45,6 +45,7 @@
 #include "log.h"
 #include "httprequest.h"
 #include "httplistener.h"
+#include "srvctrl.h"
 
 #include "configmanager.h"
 
@@ -83,7 +84,7 @@
  */
 void sig_term(int sig) {
     webserver_shutdown();
-    exit(EXIT_SUCCESS);
+    //exit(EXIT_SUCCESS);
 }
 
 void* log_pipe_thread(void *data) {
@@ -101,29 +102,6 @@
     return NULL;
 }
 
-void handle_srvctrl() {
-    int srvctrl = webserver_srvctrl_fd();
-    listen(srvctrl, 8);
-    
-    for(;;) {
-        int admin_client = accept(srvctrl, NULL, 0);
-        if(admin_client < 0) {
-            log_ereport(
-                    LOG_FAILURE,
-                    "srvctrl: accept failed: %s",
-                    strerror(errno));
-            continue;
-        }
-        
-        // TODO: read commands
-        webserver_shutdown();
-        
-        close(admin_client);
-        
-        break;
-    }
-}
-
 int main(int argc, char **argv) {
     //test();
     
@@ -199,7 +177,9 @@
         return EXIT_FAILURE;
     }
     
-    handle_srvctrl();
+    if(srvctrl_wait()) {
+        return EXIT_FAILURE;
+    }
     
     /* TODO: join threads (or not?) */
 /*
--- a/src/server/daemon/objs.mk	Tue Jan 24 22:48:14 2017 +0100
+++ b/src/server/daemon/objs.mk	Wed Jan 25 11:50:19 2017 +0100
@@ -44,6 +44,7 @@
 DAEMONOBJ += sessionhandler.o
 DAEMONOBJ += vserver.o
 DAEMONOBJ += webserver.o
+DAEMONOBJ += srvctrl.o
 DAEMONOBJ += ws-fn.o
 DAEMONOBJ += configmanager.o
 DAEMONOBJ += log.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/daemon/srvctrl.c	Wed Jan 25 11:50:19 2017 +0100
@@ -0,0 +1,187 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2017 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "webserver.h"
+
+#include "../util/systhr.h"
+
+#include "../../ucx/utils.h"
+#include "../../ucx/buffer.h"
+
+#include "srvctrl.h"
+
+#define SRVCTRL_THREAD_STACKSIZE 8192
+
+static int srvctrl;
+static WSBool srv_shutdown;
+
+int srvctrl_init(ServerConfiguration *cfg) {
+    // create srvctrl unix domain socket
+    // this socket is used for stop, reconfigure and other operations
+    sstr_t uds_path = ucx_sprintf("%s/private/srvctrl.sock", cfg->tmp.ptr);
+    struct sockaddr_un addr;
+    if(uds_path.length > sizeof(addr.sun_path)-1) {
+        log_ereport(
+                LOG_CATASTROPHE,
+                "path '%s' too long for unix domain socket",
+                uds_path.ptr);
+        return -1;
+    }
+    
+    // make sure there is no old srvctrl socket file
+    // otherweise bind would fail
+    if(unlink(uds_path.ptr)) {
+        if(errno != ENOENT) {
+            log_ereport(
+                    LOG_CATASTROPHE,
+                    "cannot unlink old srvctrl socket '%s': %s",
+                    uds_path.ptr,
+                    strerror(errno));
+            return -1;
+        }
+    }
+
+    ZERO(&addr, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    memcpy(addr.sun_path, uds_path.ptr, uds_path.length);
+    
+    srvctrl = socket(AF_UNIX, SOCK_STREAM, 0);
+    if(srvctrl == -1) {
+        log_ereport(
+                LOG_CATASTROPHE,
+                "Cannot create server control socket: %s",
+                strerror(errno));
+        return -1;
+    }
+    if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) {
+        log_ereport(
+                LOG_CATASTROPHE,
+                "srvctrl socket bind failed: %s",
+                strerror(errno));
+        return -1;
+    }
+    
+    free(uds_path.ptr);
+    
+    return 0;
+}
+
+int srvctrl_wait() {
+    listen(srvctrl, 8);
+    
+    for(;;) {
+        int fd = accept(srvctrl, NULL, 0);
+        if(fd < 0) {
+            if(srv_shutdown) {
+                break;
+            }
+            
+            log_ereport(
+                    LOG_FAILURE,
+                    "srvctrl: accept failed: %s",
+                    strerror(errno));
+            continue;
+        }
+        
+        SrvCtrlClient *client = srvctrl_create_client(fd);
+        SYS_THREAD t = systhread_start(
+                SYSTHREAD_DEFAULT_PRIORITY,
+                SRVCTRL_THREAD_STACKSIZE,
+                (thrstartfunc)srvctrl_thread,
+                client);
+        systhread_detach(t);
+        
+    }
+}
+
+void srvctrl_shutdown() {
+    srv_shutdown = TRUE;
+    close(srvctrl);
+}
+
+SrvCtrlClient* srvctrl_create_client(int fd) {
+    SrvCtrlClient *client = malloc(sizeof(SrvCtrlClient));
+    ZERO(client, sizeof(SrvCtrlClient));
+    client->fd = fd;      
+    return client;
+}
+
+void* srvctrl_thread(SrvCtrlClient *client) {
+    char buf[64];
+    UcxBuffer *line = ucx_buffer_new(NULL, 32, UCX_BUFFER_AUTOEXTEND);
+    
+    ssize_t r;
+    WSBool br = FALSE;
+    while((r = read(client->fd, buf, 64)) > 0) {
+        for(int i=0;i<r;i++) {
+            char c = buf[i];
+            if(c == '\n') {
+                sstr_t ln = sstrn(line->space, line->pos);
+                if(srvctrl_handle_cmd(client, ln)) {
+                    br = TRUE;
+                    break;
+                }
+            } else {
+                ucx_buffer_putc(line, c);
+            }
+        }
+        if(br) {
+            break;
+        }
+    }
+    
+    ucx_buffer_free(line);
+    close(client->fd);
+    free(client);
+    
+    return NULL;
+}
+
+int srvctrl_handle_cmd(SrvCtrlClient *client, sstr_t cmd) {
+    if(!sstrcmp(cmd, S("reconfig"))) {
+        write(client->fd, "reconfig\n", 9);
+        
+        if(webserver_reconfig()) {
+            log_ereport(LOG_FAILURE, "cannot reload config");
+        } else {
+            log_ereport(LOG_INFORM, "reconfig: success");
+        }
+    } else if(!sstrcmp(cmd, S("shutdown"))) {
+        webserver_shutdown();
+    } else {
+        log_ereport(
+                LOG_FAILURE,
+                "unknown srvctrl command: %.*s",
+                (int)cmd.length,
+                cmd.ptr);
+    }
+    return 1;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/daemon/srvctrl.h	Wed Jan 25 11:50:19 2017 +0100
@@ -0,0 +1,63 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2017 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef SRVCTRL_H
+#define SRVCTRL_H
+
+#include "../public/nsapi.h"
+
+#include "../../ucx/string.h"
+
+#include "config.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    int fd;
+} SrvCtrlClient;
+    
+int srvctrl_init(ServerConfiguration *cfg);
+
+int srvctrl_wait();
+
+void srvctrl_shutdown();
+
+SrvCtrlClient* srvctrl_create_client(int fd);
+
+void* srvctrl_thread(SrvCtrlClient *client);
+int srvctrl_handle_cmd(SrvCtrlClient *client, sstr_t cmd);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SRVCTRL_H */
+
--- a/src/server/daemon/webserver.c	Tue Jan 24 22:48:14 2017 +0100
+++ b/src/server/daemon/webserver.c	Wed Jan 25 11:50:19 2017 +0100
@@ -59,13 +59,12 @@
 #include "webserver.h"
 #include "log.h"
 #include "auth.h"
+#include "srvctrl.h"
 
 extern struct FuncStruct webserver_funcs[];
 
 static RestartCallback *atrestart;
 
-static int srvctrl;
-
 int webserver_init() { 
     // init NSPR
     systhread_init("webserver");
@@ -198,51 +197,9 @@
     
     // create srvctrl unix domain socket
     // this socket is used for stop, reconfigure and other operations
-    sstr_t uds_path = ucx_sprintf("%s/private/srvctrl.sock", cfg->tmp.ptr);
-    struct sockaddr_un addr;
-    if(uds_path.length > sizeof(addr.sun_path)-1) {
-        log_ereport(
-                LOG_CATASTROPHE,
-                "path '%s' too long for unix domain socket",
-                uds_path.ptr);
+    if(srvctrl_init(cfg)) {
         return -1;
-    }
-    
-    // make sure there is no old srvctrl socket file
-    // otherweise bind would fail
-    if(unlink(uds_path.ptr)) {
-        if(errno != ENOENT) {
-            log_ereport(
-                    LOG_CATASTROPHE,
-                    "cannot unlink old srvctrl socket '%s': %s",
-                    uds_path.ptr,
-                    strerror(errno));
-            return -1;
-        }
-    }
-
-    ZERO(&addr, sizeof(addr));
-    addr.sun_family = AF_UNIX;
-    memcpy(addr.sun_path, uds_path.ptr, uds_path.length);
-    
-    srvctrl = socket(AF_UNIX, SOCK_STREAM, 0);
-    if(srvctrl == -1) {
-        log_ereport(
-                LOG_CATASTROPHE,
-                "Cannot create server control socket: %s",
-                strerror(errno));
-        return -1;
-    }
-    if(bind(srvctrl, (struct sockaddr*)&addr, sizeof(addr))) {
-        log_ereport(
-                LOG_CATASTROPHE,
-                "srvctrl socket bind failed: %s",
-                strerror(errno));
-        return -1;
-    }
-    
-    free(uds_path.ptr);
-    
+    }    
     
     //endpwent(); // TODO: close or not?
     //free(pwbuf); // TODO: ?
@@ -266,6 +223,8 @@
 void webserver_shutdown() {
     log_ereport(LOG_INFORM, "webserver shutdown");
     
+    srvctrl_shutdown();
+    
     // execute restart callbacks
     RestartCallback *re = atrestart;
     while(re) {
@@ -274,8 +233,14 @@
     }
 }
 
-int webserver_srvctrl_fd() {
-    return srvctrl;
+int webserver_reconfig() {
+    if(cfgmgr_load_config(NULL) != 0) {
+        return -1;
+    }
+    // start newly created listeners
+    start_all_listener();
+    
+    return 0;
 }
 
 void webserver_atrestart(void (*fn)(void *), void *data) {
--- a/src/server/daemon/webserver.h	Tue Jan 24 22:48:14 2017 +0100
+++ b/src/server/daemon/webserver.h	Wed Jan 25 11:50:19 2017 +0100
@@ -45,8 +45,7 @@
 int webserver_init();
 int webserver_run();
 void webserver_shutdown();
-
-int webserver_srvctrl_fd();
+int webserver_reconfig();
 
 void webserver_atrestart(void (*fn)(void *), void *data);
 

mercurial