tlsgate

TLS reverse proxy
git clone git://git.akobets.xyz/tlsgate
Log | Files | Refs | README | LICENSE

commit fe985a999500c65f9ca4a9bad7ab19c69b702b95
parent 39744c8a9c981460b01349791873bfaca262002e
Author: Artem Kobets <artem@akobets.xyz>
Date:   Sat, 19 Sep 2020 18:23:46 +0300

signal handling

when SIGTERM or SIGINT is sent to process, also send it to all
children (connections). Added one more fork() to implement this.

Diffstat:
Mmain.c | 110+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
1 file changed, 79 insertions(+), 31 deletions(-)

diff --git a/main.c b/main.c @@ -17,6 +17,8 @@ static void serve(struct tls *ctx, int cfd); static void sigchld(int unused); +static void sigcleanup(int sig); +static void handle_termsignals(void(*func)(int)); static void usage(void); char *argv0; @@ -192,7 +194,33 @@ cleanup: static void sigchld(int unused) { - while (wait(NULL) != -1); + while (waitpid(-1, NULL, WNOHANG) > 0); +} + +static void +sigcleanup(int sig) +{ + struct sigaction act; + + // cleanup(); + kill(0, sig); + + act.sa_handler = SIG_DFL; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(sig, &act, NULL); +} + +static void +handle_termsignals(void(*func)(int)) +{ + struct sigaction act; + + act.sa_handler = func; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGTERM, &act, NULL); + sigaction(SIGINT, &act, NULL); } static void @@ -213,13 +241,12 @@ main(int argc, char **argv) int opt; struct tls *ctx; struct tls_config *config; - int fd; + int fd, cfd; struct sigaction act; - sigset_t sigmask; argv0 = argv[0]; - while ((opt = getopt(argc, argv, "c:k:C:h:p:H:P:U:n:v")) != -1) { + while ((opt = getopt(argc, argv, "c:k:C:h:p:H:P:U:v")) != -1) { switch (opt) { case 'c': cert_file = optarg; @@ -284,39 +311,60 @@ main(int argc, char **argv) if (tls_configure(ctx, config) == -1) err("tls_configure"); + // set new process group + // so only children will be killed with kill(0, sig) + setpgid(0, 0); + + handle_termsignals(sigcleanup); + // setup proxy socket fd = sock_proxy_ips(proxy_host, proxy_port); - // reap children - act.sa_handler = sigchld; - sigemptyset(&sigmask); - act.sa_mask = sigmask; - act.sa_flags = 0; - sigaction(SIGCHLD, &act, NULL); + switch (fork()) { + case 0: + // signal handlers were copied with fork + // restore default signal handlers + // so that only parent process performs cleanup + handle_termsignals(SIG_DFL); - while (1) { - pid_t pid; - int cfd = -1; + // reap children + act.sa_handler = sigchld; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGCHLD, &act, NULL); - if ((cfd = accept(fd, NULL, NULL)) == -1) { - // can be interrupted with SIGCHLD - if (errno != EINTR) - warn("accept"); - continue; - } + while (1) { + if ((cfd = accept(fd, NULL, NULL)) == -1) { + // can be interrupted with SIGCHLD + if (errno != EINTR) + warn("accept"); + continue; + } - switch (pid = fork()) { - case 0: { - serve(ctx, cfd); - _exit(0); - } - case -1: - warn("fork"); - close(cfd); - break; - default: - close(cfd); - break; + switch (fork()) { + case 0: + serve(ctx, cfd); + exit(0); + case -1: + warn("fork"); + close(cfd); + break; + default: + close(cfd); + break; + } } + // unreachable + exit(1); + break; + case -1: + warn("fork:"); + break; + default: + while (wait(NULL) != -1); + break; } + + // cleanup(); + return 1; }