Multi processing -> multi threading
This commit is contained in:
160
src/server.c
160
src/server.c
@ -27,7 +27,6 @@
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <wait.h>
|
||||
#include <sys/types.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/pem.h>
|
||||
@ -35,11 +34,20 @@
|
||||
#include <openssl/conf.h>
|
||||
|
||||
|
||||
volatile sig_atomic_t active = 1;
|
||||
volatile sig_atomic_t alive = 1;
|
||||
const char *config_file;
|
||||
int sockets[NUM_SOCKETS];
|
||||
pid_t children[MAX_CHILDREN];
|
||||
SSL_CTX *contexts[CONFIG_MAX_CERT_CONFIG];
|
||||
|
||||
static int sockets[NUM_SOCKETS];
|
||||
static sock clients[MAX_CHILDREN];
|
||||
static pthread_t children[MAX_CHILDREN];
|
||||
static SSL_CTX *contexts[CONFIG_MAX_CERT_CONFIG];
|
||||
|
||||
static int clean() {
|
||||
remove("/var/sesimos/server/cache");
|
||||
rmdir("/var/sesimos/server/");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) {
|
||||
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
|
||||
@ -50,42 +58,38 @@ static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) {
|
||||
return SSL_TLSEXT_ERR_OK;
|
||||
}
|
||||
|
||||
void terminate_forcefully(int sig) {
|
||||
static void accept_cb() {
|
||||
|
||||
}
|
||||
|
||||
static void accept_err_cb() {
|
||||
|
||||
}
|
||||
|
||||
static void terminate_forcefully(int sig) {
|
||||
fprintf(stderr, "\n");
|
||||
notice("Terminating forcefully!");
|
||||
|
||||
int status = 0;
|
||||
int ret;
|
||||
int kills = 0;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (children[i] != 0) {
|
||||
ret = waitpid(children[i], &status, WNOHANG);
|
||||
if (ret < 0) {
|
||||
if ((ret = pthread_kill(children[i], SIGKILL)) < 0) {
|
||||
errno = ret;
|
||||
error("Unable to wait for child process (PID %i)", children[i]);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
error("Child process with PID %i terminated with exit code %i", ret, status);
|
||||
}
|
||||
} else {
|
||||
kill(children[i], SIGKILL);
|
||||
kills++;
|
||||
errno = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (kills > 0) {
|
||||
notice("Killed %i child process(es)", kills);
|
||||
}
|
||||
cache_unload();
|
||||
|
||||
geoip_free();
|
||||
exit(2);
|
||||
}
|
||||
|
||||
void terminate_gracefully(int sig) {
|
||||
static void terminate_gracefully(int sig) {
|
||||
fprintf(stderr, "\n");
|
||||
notice("Terminating gracefully...");
|
||||
|
||||
active = 0;
|
||||
alive = 0;
|
||||
signal(SIGINT, terminate_forcefully);
|
||||
signal(SIGTERM, terminate_forcefully);
|
||||
|
||||
@ -94,54 +98,19 @@ void terminate_gracefully(int sig) {
|
||||
close(sockets[i]);
|
||||
}
|
||||
|
||||
int status = 0;
|
||||
int wait_num = 0;
|
||||
int ret;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (children[i] != 0) {
|
||||
ret = waitpid(children[i], &status, WNOHANG);
|
||||
ret = pthread_kill(children[i], SIGKILL);
|
||||
if (ret < 0) {
|
||||
critical("Unable to wait for child process (PID %i)", children[i]);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
critical("Child process with PID %i terminated with exit code %i", ret, status);
|
||||
}
|
||||
} else {
|
||||
kill(children[i], SIGTERM);
|
||||
wait_num++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_num > 0) {
|
||||
notice("Waiting for %i child process(es)...", wait_num);
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (children[i] != 0) {
|
||||
ret = waitpid(children[i], &status, 0);
|
||||
if (ret < 0) {
|
||||
critical("Unable to wait for child process (PID %i)", children[i]);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
critical("Child process with PID %i terminated with exit code %i", ret, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (wait_num > 0) {
|
||||
// Wait another 50 ms to let child processes write to stdout/stderr
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
struct timespec ts = {.tv_sec = 0, .tv_nsec = 50000000};
|
||||
nanosleep(&ts, &ts);
|
||||
}
|
||||
|
||||
info("Goodbye");
|
||||
cache_unload();
|
||||
geoip_free();
|
||||
exit(0);
|
||||
}
|
||||
@ -153,9 +122,6 @@ int main(int argc, char *const argv[]) {
|
||||
long client_num = 0;
|
||||
int ret;
|
||||
|
||||
int client_fd;
|
||||
sock client;
|
||||
|
||||
memset(sockets, 0, sizeof(sockets));
|
||||
memset(children, 0, sizeof(children));
|
||||
|
||||
@ -164,6 +130,8 @@ int main(int argc, char *const argv[]) {
|
||||
{.sin6_family = AF_INET6, .sin6_addr = IN6ADDR_ANY_INIT, .sin6_port = htons(443)}
|
||||
};
|
||||
|
||||
logger_init();
|
||||
|
||||
logger_set_name("server");
|
||||
|
||||
if (setvbuf(stdout, NULL, _IOLBF, 0) != 0 || setvbuf(stderr, NULL, _IOLBF, 0) != 0) {
|
||||
@ -239,14 +207,10 @@ int main(int argc, char *const argv[]) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
ret = cache_init();
|
||||
if (ret < 0) {
|
||||
if ((ret = cache_init()) != 0) {
|
||||
geoip_free();
|
||||
if (ret == -1) critical("Unable to initialize cache");
|
||||
return 1;
|
||||
} else if (ret != 0) {
|
||||
children[0] = ret; // pid
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < CONFIG_MAX_CERT_CONFIG; i++) {
|
||||
@ -265,27 +229,21 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
if (SSL_CTX_use_certificate_chain_file(ctx, conf->full_chain) != 1) {
|
||||
critical("Unable to load certificate chain file: %s: %s", ERR_reason_error_string(ERR_get_error()), conf->full_chain);
|
||||
cache_unload();
|
||||
geoip_free();
|
||||
return 1;
|
||||
}
|
||||
if (SSL_CTX_use_PrivateKey_file(ctx, conf->priv_key, SSL_FILETYPE_PEM) != 1) {
|
||||
critical("Unable to load private key file: %s: %s", ERR_reason_error_string(ERR_get_error()), conf->priv_key);
|
||||
cache_unload();
|
||||
geoip_free();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
client.ctx = contexts[0];
|
||||
|
||||
|
||||
proxy_preload();
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
if (listen(sockets[i], LISTEN_BACKLOG) < 0) {
|
||||
critical("Unable to listen on socket %i", i);
|
||||
cache_unload();
|
||||
geoip_free();
|
||||
return 1;
|
||||
}
|
||||
@ -299,7 +257,7 @@ int main(int argc, char *const argv[]) {
|
||||
errno = 0;
|
||||
notice("Ready to accept connections");
|
||||
|
||||
while (active) {
|
||||
while (alive) {
|
||||
ready_sockets_num = poll(poll_fds, NUM_SOCKETS, 1000);
|
||||
if (ready_sockets_num < 0) {
|
||||
critical("Unable to poll sockets");
|
||||
@ -309,56 +267,48 @@ int main(int argc, char *const argv[]) {
|
||||
|
||||
for (int i = 0; i < NUM_SOCKETS; i++) {
|
||||
if (poll_fds[i].revents & POLLIN) {
|
||||
socklen_t addr_len = sizeof(client.addr);
|
||||
client_fd = accept(sockets[i], &client.addr.sock, &addr_len);
|
||||
int j;
|
||||
for (j = 0; j < MAX_CHILDREN; j++) {
|
||||
if (children[j] == 0) break;
|
||||
}
|
||||
sock *client = &clients[j];
|
||||
|
||||
client->ctx = contexts[0];
|
||||
socklen_t addr_len = sizeof(client->addr);
|
||||
int client_fd = accept(sockets[i], &client->addr.sock, &addr_len);
|
||||
if (client_fd < 0) {
|
||||
critical("Unable to accept connection");
|
||||
continue;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
// child
|
||||
signal(SIGINT, SIG_IGN);
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
|
||||
client.socket = client_fd;
|
||||
client.enc = (i == 1);
|
||||
return client_handler(&client, client_num);
|
||||
} else if (pid > 0) {
|
||||
// parent
|
||||
client_num++;
|
||||
close(client_fd);
|
||||
for (int j = 0; j < MAX_CHILDREN; j++) {
|
||||
if (children[j] == 0) {
|
||||
children[j] = pid;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
client->socket = client_fd;
|
||||
client->enc = (i == 1);
|
||||
ret = pthread_create(&children[j], NULL, (void *(*)(void *)) &client_handler, client);
|
||||
if (ret != 0) {
|
||||
errno = ret;
|
||||
critical("Unable to create child process");
|
||||
}
|
||||
|
||||
client_num++;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO outsource in thread
|
||||
int status = 0;
|
||||
/*
|
||||
void *ret_val = NULL;
|
||||
for (int i = 0; i < MAX_CHILDREN; i++) {
|
||||
if (children[i] != 0) {
|
||||
ret = waitpid(children[i], &status, WNOHANG);
|
||||
ret = pthread_timed(children[i], &ret_val);
|
||||
if (ret < 0) {
|
||||
critical("Unable to wait for child process (PID %i)", children[i]);
|
||||
critical("Unable to wait for thread (PID %i)", children[i]);
|
||||
} else if (ret == children[i]) {
|
||||
children[i] = 0;
|
||||
if (status != 0) {
|
||||
critical("Child process with PID %i terminated with exit code %i", ret, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
cache_unload();
|
||||
geoip_free();
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user