sslbd/common.cpp
#include "common.hpp"
#include "config.hpp"
#include "hooks.hpp"
#include <sys/syscall.h>
#include <sys/time.h>
#include <execinfo.h>
#include <fcntl.h>
struct loglevels_s loglevels = {
"[io] ",
"[dbg] ",
"[info]",
"[note]",
TERM_RED "[err] " TERM_RESET,
};
loglevel_t* loglevel = &loglevels.io; // the default
const logctx_t* logctx = NULL;
static bool loglevel_set(void*& ctx, char* s) {
for (loglevel_t* l = (loglevel_t*)&loglevels; l < (loglevel_t*)((char*)&loglevels + sizeof(loglevels)); ++l) {
if (strstr((const char*)*l, s)) {
#ifndef DEBUG
if (l < &loglevels.info) return false;
#endif
loglevel = l;
return true;
}
}
return false;
}
static bool pidfile_set(void*& ctx, char* s) {
int pid = (int)getpid();
int fd = open(s, O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if (fd == -1) {
log_errno(error, "cannot open pidfile %s", s);
return false;
}
(void)dprintf(fd, "%d\n", pid);
EINTR_RETRY(close(fd));
log(info, "wrote %d to %s", pid, s);
ctx = (void*)strdup(s);
return true;
}
static void pidfile_unset(void*& ctx) {
if (ctx) {
if (unlink((char*)ctx) == -1) {
log_errno(error, "unlink(%s)", (char*)ctx); // but pretend success
} else {
log(debug, "removed %s", (char*)ctx);
}
safe_free(ctx);
}
}
CONF_DEF(config) {
ConfigKey loglevel;
ConfigKey pid_file;
};
CONF_INIT(config) {
CONF_KEY_INIT(loglevel, true, false, &loglevel_set, NULL);
CONF_KEY_INIT(pid_file, false, false, &pidfile_set, &pidfile_unset);
}
#define gettid() syscall(SYS_gettid) // not in glibc
bool in_main_thread() {
return getpid() == gettid();
}
int null_fd() {
static int fd = open("/dev/null", O_RDWR);
assert(fd != -1);
return fd; // dup?
}
time_t* BEFORE_NOW = &NOW - 1;
time_t NOW = 0;
msec_t NOW_MSEC;
char NOW_STR[cstrlen("Sun Sep 16 01:03:52 1973")+1] = {};
void update_now() {
#if 0
NOW = time(NULL);
NOW_MSEC = NOW*1000;
#else
struct timeval tv;
(void)gettimeofday(&tv, NULL);
NOW = tv.tv_sec; // TODO: round?
NOW_MSEC = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
#endif
ctime_r(&NOW, NOW_STR);
NOW_STR[cstrlen("Sun Sep 16 01:03:52 1973")] = '\0';
}
HOOK_ADD(&update_now, INIT, HOOK_PRIO_EARLY);
int RECONFIGURE=0;
int CLEANUP=0;
shutdown_e SHUTDOWN=SHUTDOWN_NONE;
static void signal_handler(int sig) {
if (sig == SIGSEGV) {
log_bt(STDERR_FILENO);
raise(sig); // SA_RESETHAND
} else if (sig == SIGHUP) {
++RECONFIGURE;
} else if (sig == SIGUSR1) {
++CLEANUP;
} else {
if (SHUTDOWN != SHUTDOWN_NOW) {
SHUTDOWN = (shutdown_e)((int)SHUTDOWN + 1);
}
}
}
HOOK(INIT, HOOK_PRIO_EARLY) { ///< registers signal handler(s)
static struct sigaction sa = {};
sigemptyset(&sa.sa_mask);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, NULL);
sa.sa_handler = &signal_handler;
sigaction(SIGINT, &sa, NULL);
sigaction(SIGHUP, &sa, NULL);
sigaction(SIGUSR1, &sa, NULL);
sigaction(SIGTERM, &sa, NULL); // SA_RESETHAND?
#ifdef DEBUG
sa.sa_flags = SA_RESETHAND;
sigaction(SIGSEGV, &sa, NULL);
#endif
}
const char* src_basename(const char* fn) {
static int off = -1;
if (unlikely(off == -1)) {
const char* a = __FILE__;
const char* b = strrchr(a, '/');
if (b) {
off = b-a;
} else {
off = 0;
}
}
return fn + off;
}
void log_bt(int fd) {
static void* arr[4096];
int n = backtrace(arr, 4096);
if (fd != -1) {
backtrace_symbols_fd(arr, n, fd);
} else {
char** bt = backtrace_symbols(arr, n);
if (!bt) return;
while (n-- > 0) log(error, "backtrace: %s", *bt++);
}
}