Wed, 25 Jan 2017 11:50:19 +0100
adds reconfig and shutdown handler to srvctrl
--- 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);