Impl. hot reloading of config and on SIGUSR1
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 40s
All checks were successful
Run Unit Tests / build-and-run-unit-tests (push) Successful in 40s
Resolves #2
This commit is contained in:
parent
bc879408fe
commit
bf7bfe5c86
7 changed files with 113 additions and 1 deletions
|
@ -29,6 +29,7 @@ void print_usage(void) {
|
|||
puts(" --req-header-to-print=<header> (can be used multiple times)");
|
||||
puts(" For example: --req-header-to-print=User-Agent");
|
||||
puts(" Note that this option is case-insensitive");
|
||||
puts(" --enable-reload-config-on-change");
|
||||
}
|
||||
|
||||
Args parse_args(int argc, char **argv) {
|
||||
|
@ -66,6 +67,8 @@ Args parse_args(int argc, char **argv) {
|
|||
free(header_buf);
|
||||
exit(1);
|
||||
}
|
||||
} else if (strcmp(argv[0], "--enable-reload-config-on-change") == 0) {
|
||||
args.flags |= 2;
|
||||
} else {
|
||||
puts("ERROR: Invalid args!\n");
|
||||
print_usage();
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
typedef struct Args {
|
||||
// xxxx xxx0 - enable peer addr print.
|
||||
// xxxx xxx1 - disable peer addr print.
|
||||
// xxxx xx0x - disable listen on config file for reloading.
|
||||
// xxxx xx1x - enable listen on config file for reloading.
|
||||
unsigned short flags;
|
||||
unsigned short port;
|
||||
// Does not need to be free'd, this should point to a string in argv.
|
||||
|
|
|
@ -17,5 +17,6 @@
|
|||
#include "globals.h"
|
||||
|
||||
int C_SIMPLE_HTTP_KEEP_RUNNING = 1;
|
||||
int C_SIMPLE_HTTP_SIGUSR1_SET = 0;
|
||||
|
||||
// vim: et ts=2 sts=2 sw=2
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_GLOBALS_H_
|
||||
|
||||
extern int C_SIMPLE_HTTP_KEEP_RUNNING;
|
||||
extern int C_SIMPLE_HTTP_SIGUSR1_SET;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
97
src/main.c
97
src/main.c
|
@ -19,13 +19,15 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// Unix includes.
|
||||
// Linux/Unix includes.
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <linux/limits.h>
|
||||
|
||||
// Third party includes.
|
||||
#include <SimpleArchiver/src/helpers.h>
|
||||
|
@ -64,6 +66,13 @@ int c_simple_http_headers_check_print(void *data, void *ud) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void c_simple_http_inotify_fd_cleanup(int *fd) {
|
||||
if (fd && *fd >= 0) {
|
||||
close(*fd);
|
||||
*fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
__attribute__((cleanup(c_simple_http_free_args)))
|
||||
Args args = parse_args(argc, argv);
|
||||
|
@ -103,6 +112,34 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
__attribute__((cleanup(c_simple_http_inotify_fd_cleanup)))
|
||||
int inotify_config_fd = -1;
|
||||
__attribute__((cleanup(simple_archiver_helper_cleanup_malloced)))
|
||||
void *inotify_event_buf = NULL;
|
||||
struct inotify_event *inotify_event = NULL;
|
||||
const size_t inotify_event_buf_size =
|
||||
sizeof(struct inotify_event) + NAME_MAX + 1;
|
||||
if ((args.flags & 0x2) != 0) {
|
||||
inotify_config_fd = inotify_init1(IN_NONBLOCK);
|
||||
if (inotify_config_fd < 0) {
|
||||
fprintf(stderr, "ERROR Failed to init listen on config file for hot "
|
||||
"reloading! (error code \"%d\")\n", errno);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if (inotify_add_watch(
|
||||
inotify_config_fd,
|
||||
args.config_file,
|
||||
IN_MODIFY | IN_CLOSE_WRITE) == -1) {
|
||||
fprintf(stderr, "ERROR Failed to set up listen on config file for hot "
|
||||
"reloading! (error code \"%d\")\n", errno);
|
||||
return 4;
|
||||
}
|
||||
|
||||
inotify_event_buf = malloc(inotify_event_buf_size);
|
||||
inotify_event = inotify_event_buf;
|
||||
}
|
||||
|
||||
struct timespec sleep_time;
|
||||
sleep_time.tv_sec = 0;
|
||||
sleep_time.tv_nsec = C_SIMPLE_HTTP_SLEEP_NANOS;
|
||||
|
@ -112,6 +149,7 @@ int main(int argc, char **argv) {
|
|||
peer_info.sin6_family = AF_INET6;
|
||||
|
||||
signal(SIGINT, C_SIMPLE_HTTP_handle_sigint);
|
||||
signal(SIGUSR1, C_SIMPLE_HTTP_handle_sigusr1);
|
||||
|
||||
unsigned char recv_buf[C_SIMPLE_HTTP_RECV_BUF_SIZE];
|
||||
|
||||
|
@ -121,6 +159,63 @@ int main(int argc, char **argv) {
|
|||
|
||||
while (C_SIMPLE_HTTP_KEEP_RUNNING) {
|
||||
nanosleep(&sleep_time, NULL);
|
||||
|
||||
if (C_SIMPLE_HTTP_SIGUSR1_SET) {
|
||||
// Handle hot-reloading of config file due to SIGUSR1.
|
||||
C_SIMPLE_HTTP_SIGUSR1_SET = 0;
|
||||
fprintf(stderr, "NOTICE SIGUSR1, reloading config file...\n");
|
||||
c_simple_http_clean_up_parsed_config(&parsed_config);
|
||||
parsed_config = c_simple_http_parse_config(
|
||||
args.config_file,
|
||||
"PATH",
|
||||
NULL);
|
||||
}
|
||||
if ((args.flags & 0x2) != 0) {
|
||||
// Handle hot-reloading of config file.
|
||||
read_ret =
|
||||
read(inotify_config_fd, inotify_event_buf, inotify_event_buf_size);
|
||||
if (read_ret == -1) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
// No events, do nothing.
|
||||
} else {
|
||||
fprintf(
|
||||
stderr,
|
||||
"WARNING Error code \"%d\" on config file listen for hot "
|
||||
"reloading!\n",
|
||||
errno);
|
||||
}
|
||||
} else if (read_ret > 0) {
|
||||
#ifndef NDEBUG
|
||||
printf("DEBUG inotify_event->mask: %x\n", inotify_event->mask);
|
||||
#endif
|
||||
if ((inotify_event->mask & IN_MODIFY) != 0
|
||||
|| (inotify_event->mask & IN_CLOSE_WRITE) != 0) {
|
||||
fprintf(stderr, "NOTICE Config file modified, reloading...\n");
|
||||
c_simple_http_clean_up_parsed_config(&parsed_config);
|
||||
parsed_config = c_simple_http_parse_config(
|
||||
args.config_file,
|
||||
"PATH",
|
||||
NULL);
|
||||
} else if ((inotify_event->mask & IN_IGNORED) != 0) {
|
||||
fprintf(
|
||||
stderr,
|
||||
"NOTICE Config file modified (IN_IGNORED), reloading...\n");
|
||||
c_simple_http_clean_up_parsed_config(&parsed_config);
|
||||
parsed_config = c_simple_http_parse_config(
|
||||
args.config_file,
|
||||
"PATH",
|
||||
NULL);
|
||||
// Re-initialize inotify.
|
||||
//c_simple_http_inotify_fd_cleanup(&inotify_config_fd);
|
||||
//inotify_config_fd = inotify_init1(IN_NONBLOCK);
|
||||
inotify_add_watch(
|
||||
inotify_config_fd,
|
||||
args.config_file,
|
||||
IN_MODIFY | IN_CLOSE_WRITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
socket_len = sizeof(struct sockaddr_in6);
|
||||
ret = accept(tcp_socket, (struct sockaddr *)&peer_info, &socket_len);
|
||||
if (ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) {
|
||||
|
|
|
@ -34,4 +34,13 @@ void C_SIMPLE_HTTP_handle_sigint(int signal) {
|
|||
}
|
||||
}
|
||||
|
||||
void C_SIMPLE_HTTP_handle_sigusr1(int signal) {
|
||||
if (signal == SIGUSR1) {
|
||||
#ifndef NDEBUG
|
||||
puts("Handling SIGUSR1");
|
||||
#endif
|
||||
C_SIMPLE_HTTP_SIGUSR1_SET = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// vim: et ts=2 sts=2 sw=2
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#define SEODISPARATE_COM_C_SIMPLE_HTTP_SIGNAL_HANDLING_H_
|
||||
|
||||
void C_SIMPLE_HTTP_handle_sigint(int signal);
|
||||
void C_SIMPLE_HTTP_handle_sigusr1(int signal);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Reference in a new issue