mirror of https://github.com/omar-polo/gmid.git
reload configuration on SIGHUP
This commit is contained in:
parent
1e3ef7ab4f
commit
ca21e10043
|
@ -1,3 +1,7 @@
|
|||
2021-02-04 Omar Polo <op@omarpolo.com>
|
||||
|
||||
* gmid.c (main): reload configuration on SIGHUP, without disconnecting the clients
|
||||
|
||||
2021-02-02 Omar Polo <op@omarpolo.com>
|
||||
|
||||
* server.c (handle_dirlist_head): print the header in the directory listing
|
||||
|
|
5
ex.c
5
ex.c
|
@ -350,7 +350,7 @@ executor_main()
|
|||
err(1, "pledge");
|
||||
#endif
|
||||
|
||||
for (;;) {
|
||||
while (!hupped) {
|
||||
if (!recv_iri(exfd, &iri)
|
||||
|| !recv_string(exfd, &spath)
|
||||
|| !recv_string(exfd, &relpath)
|
||||
|
@ -376,6 +376,9 @@ executor_main()
|
|||
free(chash);
|
||||
}
|
||||
|
||||
if (hupped)
|
||||
_exit(0);
|
||||
|
||||
/* kill all process in my group. This means the listener and
|
||||
* every pending CGI script. */
|
||||
kill(0, SIGINT);
|
||||
|
|
110
gmid.c
110
gmid.c
|
@ -31,6 +31,8 @@
|
|||
|
||||
#include "gmid.h"
|
||||
|
||||
volatile sig_atomic_t hupped;
|
||||
|
||||
struct vhost hosts[HOSTSLEN];
|
||||
|
||||
int exfd, foreground, verbose, sock4, sock6;
|
||||
|
@ -39,6 +41,7 @@ const char *config_path, *certs_dir, *hostname;
|
|||
|
||||
struct conf conf;
|
||||
|
||||
struct tls_config *tlsconf;
|
||||
struct tls *ctx;
|
||||
|
||||
void
|
||||
|
@ -170,6 +173,8 @@ void
|
|||
sig_handler(int sig)
|
||||
{
|
||||
(void)sig;
|
||||
|
||||
hupped = sig == SIGHUP;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -353,7 +358,6 @@ make_socket(int port, int family)
|
|||
void
|
||||
setup_tls(void)
|
||||
{
|
||||
struct tls_config *tlsconf;
|
||||
struct vhost *h;
|
||||
|
||||
if ((tlsconf = tls_config_new()) == NULL)
|
||||
|
@ -371,7 +375,8 @@ setup_tls(void)
|
|||
|
||||
/* we need to set something, then we can add how many key we want */
|
||||
if (tls_config_set_keypair_file(tlsconf, hosts->cert, hosts->key))
|
||||
fatal("tls_config_set_keypair_file failed");
|
||||
fatal("tls_config_set_keypair_file failed for (%s, %s)",
|
||||
hosts->cert, hosts->key);
|
||||
|
||||
for (h = &hosts[1]; h->domain != NULL; ++h) {
|
||||
if (tls_config_add_keypair_file(tlsconf, h->cert, h->key) == -1)
|
||||
|
@ -412,6 +417,47 @@ init_config(void)
|
|||
conf.user = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
free_config(void)
|
||||
{
|
||||
struct vhost *h;
|
||||
struct location *l;
|
||||
|
||||
free(conf.chroot);
|
||||
free(conf.user);
|
||||
memset(&conf, 0, sizeof(conf));
|
||||
|
||||
for (h = hosts; h->domain != NULL; ++h) {
|
||||
free((char*)h->domain);
|
||||
free((char*)h->cert);
|
||||
free((char*)h->key);
|
||||
free((char*)h->dir);
|
||||
free((char*)h->cgi);
|
||||
|
||||
for (l = h->locations; l->match != NULL; ++l) {
|
||||
free((char*)l->match);
|
||||
free((char*)l->lang);
|
||||
free((char*)l->default_mime);
|
||||
free((char*)l->index);
|
||||
}
|
||||
}
|
||||
memset(hosts, 0, sizeof(hosts));
|
||||
|
||||
tls_free(ctx);
|
||||
tls_config_free(tlsconf);
|
||||
}
|
||||
|
||||
static void
|
||||
wait_sighup(void)
|
||||
{
|
||||
sigset_t mask;
|
||||
int signo;
|
||||
|
||||
sigemptyset(&mask);
|
||||
sigaddset(&mask, SIGHUP);
|
||||
sigwait(&mask, &signo);
|
||||
}
|
||||
|
||||
void
|
||||
drop_priv(void)
|
||||
{
|
||||
|
@ -490,16 +536,20 @@ serve(int argc, char **argv, int *p)
|
|||
fatal("fork: %s", strerror(errno));
|
||||
|
||||
case 0: /* child */
|
||||
setproctitle("listener");
|
||||
close(p[0]);
|
||||
exfd = p[1];
|
||||
drop_priv();
|
||||
unblock_signals();
|
||||
listener_main();
|
||||
_exit(0);
|
||||
|
||||
default: /* parent */
|
||||
setproctitle("executor");
|
||||
close(p[1]);
|
||||
exfd = p[0];
|
||||
drop_priv();
|
||||
unblock_signals();
|
||||
return executor_main();
|
||||
}
|
||||
}
|
||||
|
@ -509,6 +559,7 @@ main(int argc, char **argv)
|
|||
{
|
||||
int ch, p[2];
|
||||
int conftest = 0, configless = 0;
|
||||
int old_ipv6, old_port;
|
||||
|
||||
init_config();
|
||||
|
||||
|
@ -520,7 +571,7 @@ main(int argc, char **argv)
|
|||
break;
|
||||
|
||||
case 'c':
|
||||
config_path = optarg;
|
||||
config_path = absolutify_path(optarg);
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
|
@ -591,7 +642,7 @@ main(int argc, char **argv)
|
|||
signal(SIGINFO, sig_handler);
|
||||
#endif
|
||||
signal(SIGUSR2, sig_handler);
|
||||
signal(SIGHUP, SIG_IGN);
|
||||
signal(SIGHUP, sig_handler);
|
||||
|
||||
if (!foreground && !configless) {
|
||||
if (daemon(1, 1) == -1)
|
||||
|
@ -610,5 +661,54 @@ main(int argc, char **argv)
|
|||
if (conf.ipv6)
|
||||
sock6 = make_socket(conf.port, AF_INET6);
|
||||
|
||||
return serve(argc, argv, p);
|
||||
if (configless)
|
||||
return serve(argc, argv, p);
|
||||
|
||||
/* wait a sighup and reload the daemon */
|
||||
for (;;) {
|
||||
block_signals();
|
||||
|
||||
hupped = 0;
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
fatal("fork: %s", strerror(errno));
|
||||
case 0:
|
||||
return serve(argc, argv, p);
|
||||
}
|
||||
|
||||
close(p[0]);
|
||||
close(p[1]);
|
||||
|
||||
unblock_signals();
|
||||
wait_sighup();
|
||||
LOGI("reloading configuration %s", config_path);
|
||||
|
||||
old_ipv6 = conf.ipv6;
|
||||
old_port = conf.port;
|
||||
|
||||
free_config();
|
||||
init_config();
|
||||
parse_conf(config_path);
|
||||
|
||||
if (old_port != conf.port) {
|
||||
close(sock4);
|
||||
close(sock6);
|
||||
sock4 = -1;
|
||||
sock6 = -1;
|
||||
}
|
||||
|
||||
if (sock6 != -1 && old_ipv6 != conf.ipv6) {
|
||||
close(sock6);
|
||||
sock6 = -1;
|
||||
}
|
||||
|
||||
if (sock4 == -1)
|
||||
sock4 = make_socket(conf.port, AF_INET);
|
||||
if (sock6 == -1 && conf.ipv6)
|
||||
sock6 = make_socket(conf.port, AF_INET6);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC,
|
||||
PF_UNSPEC, p) == -1)
|
||||
fatal("socketpair: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
|
7
gmid.h
7
gmid.h
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <dirent.h>
|
||||
#include <poll.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <syslog.h>
|
||||
|
@ -109,6 +110,8 @@ struct conf {
|
|||
extern struct conf conf;
|
||||
extern int exfd;
|
||||
|
||||
extern volatile sig_atomic_t hupped;
|
||||
|
||||
struct iri {
|
||||
char *schema;
|
||||
char *host;
|
||||
|
@ -195,6 +198,7 @@ void load_vhosts(void);
|
|||
int make_socket(int, int);
|
||||
void setup_tls(void);
|
||||
void init_config(void);
|
||||
void free_config(void);
|
||||
void drop_priv(void);
|
||||
void usage(const char*);
|
||||
|
||||
|
@ -250,9 +254,12 @@ int serialize_iri(struct iri*, char*, size_t);
|
|||
int puny_decode(const char*, char*, size_t, const char**);
|
||||
|
||||
/* utils.c */
|
||||
void block_signals(void);
|
||||
void unblock_signals(void);
|
||||
int starts_with(const char*, const char*);
|
||||
int ends_with(const char*, const char*);
|
||||
ssize_t filesize(int);
|
||||
char *absolutify_path(const char*);
|
||||
char *xstrdup(const char*);
|
||||
|
||||
#endif
|
||||
|
|
16
parse.y
16
parse.y
|
@ -28,11 +28,10 @@
|
|||
* int yydebug = 1;
|
||||
*/
|
||||
|
||||
struct vhost *host = &hosts[0];
|
||||
size_t ihost = 0;
|
||||
|
||||
struct location *loc = &hosts[0].locations[0];
|
||||
size_t iloc = 0;
|
||||
struct vhost *host;
|
||||
size_t ihost;
|
||||
struct location *loc;
|
||||
size_t iloc;
|
||||
|
||||
int goterror = 0;
|
||||
const char *config_path;
|
||||
|
@ -85,7 +84,7 @@ vhosts : /* empty */
|
|||
;
|
||||
|
||||
vhost : TSERVER TSTRING '{' servopts locations '}' {
|
||||
host->locations[0].match = (char*)"*";
|
||||
host->locations[0].match = xstrdup("*");
|
||||
host->domain = $2;
|
||||
|
||||
if (strstr($2, "xn--") != NULL) {
|
||||
|
@ -183,6 +182,11 @@ parse_portno(const char *p)
|
|||
void
|
||||
parse_conf(const char *path)
|
||||
{
|
||||
host = &hosts[0];
|
||||
ihost = 0;
|
||||
loc = &hosts[0].locations[0];
|
||||
iloc = 0;
|
||||
|
||||
config_path = path;
|
||||
if ((yyin = fopen(path, "r")) == NULL)
|
||||
fatal("cannot open config %s", path);
|
||||
|
|
11
server.c
11
server.c
|
@ -906,8 +906,6 @@ loop(struct tls *ctx, int sock4, int sock6)
|
|||
struct client clients[MAX_USERS];
|
||||
struct pollfd fds[MAX_USERS];
|
||||
|
||||
connected_clients = 0;
|
||||
|
||||
for (i = 0; i < MAX_USERS; ++i) {
|
||||
fds[i].fd = -1;
|
||||
fds[i].events = POLLIN;
|
||||
|
@ -952,5 +950,14 @@ loop(struct tls *ctx, int sock4, int sock6)
|
|||
else
|
||||
clients[i].state(&fds[i], &clients[i]);
|
||||
}
|
||||
|
||||
if (hupped) {
|
||||
if (connected_clients == 0)
|
||||
return;
|
||||
|
||||
fds[0].fd = -1;
|
||||
if (sock6 != -1)
|
||||
fds[1].fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
28
utils.c
28
utils.c
|
@ -19,6 +19,24 @@
|
|||
|
||||
#include "gmid.h"
|
||||
|
||||
static sigset_t set;
|
||||
|
||||
void
|
||||
block_signals(void)
|
||||
{
|
||||
sigset_t new;
|
||||
|
||||
sigemptyset(&new);
|
||||
sigaddset(&new, SIGHUP);
|
||||
sigprocmask(SIG_BLOCK, &new, &set);
|
||||
}
|
||||
|
||||
void
|
||||
unblock_signals(void)
|
||||
{
|
||||
sigprocmask(SIG_SETMASK, &set, NULL);
|
||||
}
|
||||
|
||||
int
|
||||
starts_with(const char *str, const char *prefix)
|
||||
{
|
||||
|
@ -80,3 +98,13 @@ absolutify_path(const char *path)
|
|||
free(wd);
|
||||
return r;
|
||||
}
|
||||
|
||||
char *
|
||||
xstrdup(const char *s)
|
||||
{
|
||||
char *d;
|
||||
|
||||
if ((d = strdup(s)) == NULL)
|
||||
err(1, "strdup");
|
||||
return d;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue