Browse Source
In particular, the main daemon and subdaemons share the backtrace code, with hooks for logging. The daemon hook inserts the io_poll override, which means we no longer need io_debug.[ch]. Though most daemons don't need it, they still link against ccan/io, so it's harmess (suggested by @ZmnSCPxj). This was tested manually to make sure we get backtraces still. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>ppa-0.6.1
Rusty Russell
7 years ago
committed by
Christian Decker
24 changed files with 220 additions and 212 deletions
@ -0,0 +1,111 @@ |
|||
#include <backtrace-supported.h> |
|||
#include <backtrace.h> |
|||
#include <ccan/err/err.h> |
|||
#include <ccan/io/io.h> |
|||
#include <ccan/str/str.h> |
|||
#include <common/daemon.h> |
|||
#include <common/status.h> |
|||
#include <common/utils.h> |
|||
#include <common/version.h> |
|||
#include <poll.h> |
|||
#include <signal.h> |
|||
#include <stdio.h> |
|||
#include <stdlib.h> |
|||
#include <sys/types.h> |
|||
#include <unistd.h> |
|||
#include <wally_core.h> |
|||
|
|||
#if BACKTRACE_SUPPORTED |
|||
static struct backtrace_state *backtrace_state; |
|||
static void (*bt_print)(const char *fmt, ...) PRINTF_FMT(1,2); |
|||
static void (*bt_exit)(void); |
|||
|
|||
static int backtrace_status(void *unused UNUSED, uintptr_t pc, |
|||
const char *filename, int lineno, |
|||
const char *function) |
|||
{ |
|||
bt_print("backtrace: %s:%d (%s) %p", |
|||
filename, lineno, function, (void *)pc); |
|||
return 0; |
|||
} |
|||
|
|||
static void crashdump(int sig) |
|||
{ |
|||
/* We do stderr first, since it's most reliable. */ |
|||
warnx("Fatal signal %d", sig); |
|||
backtrace_print(backtrace_state, 0, stderr); |
|||
|
|||
/* Now send to parent. */ |
|||
bt_print("FATAL SIGNAL %d", sig); |
|||
backtrace_full(backtrace_state, 0, backtrace_status, NULL, NULL); |
|||
|
|||
/* Probably shouldn't return. */ |
|||
bt_exit(); |
|||
|
|||
/* This time it will kill us instantly. */ |
|||
kill(getpid(), sig); |
|||
} |
|||
|
|||
static void crashlog_activate(void) |
|||
{ |
|||
struct sigaction sa; |
|||
|
|||
sa.sa_handler = crashdump; |
|||
sigemptyset(&sa.sa_mask); |
|||
|
|||
/* We want to fall through to default handler */ |
|||
sa.sa_flags = SA_RESETHAND; |
|||
sigaction(SIGILL, &sa, NULL); |
|||
sigaction(SIGABRT, &sa, NULL); |
|||
sigaction(SIGFPE, &sa, NULL); |
|||
sigaction(SIGSEGV, &sa, NULL); |
|||
sigaction(SIGBUS, &sa, NULL); |
|||
} |
|||
#endif |
|||
|
|||
static int daemon_poll(struct pollfd *fds, nfds_t nfds, int timeout) |
|||
{ |
|||
const char *t; |
|||
|
|||
t = taken_any(); |
|||
if (t) |
|||
errx(1, "Outstanding taken pointers: %s", t); |
|||
|
|||
clean_tmpctx(); |
|||
|
|||
return poll(fds, nfds, timeout); |
|||
} |
|||
|
|||
void daemon_setup(const char *argv0, |
|||
void (*backtrace_print)(const char *fmt, ...), |
|||
void (*backtrace_exit)(void)) |
|||
{ |
|||
err_set_progname(argv0); |
|||
|
|||
bt_print = backtrace_print; |
|||
bt_exit = backtrace_exit; |
|||
|
|||
#if BACKTRACE_SUPPORTED |
|||
#if DEVELOPER |
|||
/* Suppresses backtrace (breaks valgrind) */ |
|||
if (!getenv("LIGHTNINGD_DEV_NO_BACKTRACE")) |
|||
backtrace_state = backtrace_create_state(argv0, 0, NULL, NULL); |
|||
#else |
|||
backtrace_state = backtrace_create_state(argv0, 0, NULL, NULL); |
|||
#endif |
|||
crashlog_activate(); |
|||
#endif |
|||
|
|||
/* We handle write returning errors! */ |
|||
signal(SIGPIPE, SIG_IGN); |
|||
secp256k1_ctx = wally_get_secp_context(); |
|||
|
|||
setup_tmpctx(); |
|||
io_poll_override(daemon_poll); |
|||
} |
|||
|
|||
void daemon_shutdown(void) |
|||
{ |
|||
tal_free(tmpctx); |
|||
wally_cleanup(0); |
|||
} |
@ -0,0 +1,13 @@ |
|||
#ifndef LIGHTNING_COMMON_DAEMON_H |
|||
#define LIGHTNING_COMMON_DAEMON_H |
|||
#include "config.h" |
|||
|
|||
/* Common setup for all daemons */ |
|||
void daemon_setup(const char *argv0, |
|||
void (*backtrace_print)(const char *fmt, ...), |
|||
void (*backtrace_exit)(void)); |
|||
|
|||
/* Shutdown for a valgrind-clean exit (frees everything) */ |
|||
void daemon_shutdown(void); |
|||
|
|||
#endif /* LIGHTNING_COMMON_DAEMON_H */ |
@ -1,17 +0,0 @@ |
|||
#include <ccan/err/err.h> |
|||
#include <ccan/take/take.h> |
|||
#include <common/io_debug.h> |
|||
#include <common/utils.h> |
|||
|
|||
int debug_poll(struct pollfd *fds, nfds_t nfds, int timeout) |
|||
{ |
|||
const char *t; |
|||
|
|||
t = taken_any(); |
|||
if (t) |
|||
errx(1, "Outstanding taken pointers: %s", t); |
|||
|
|||
clean_tmpctx(); |
|||
|
|||
return poll(fds, nfds, timeout); |
|||
} |
@ -1,9 +0,0 @@ |
|||
#ifndef LIGHTNING_COMMON_IO_DEBUG_H |
|||
#define LIGHTNING_COMMON_IO_DEBUG_H |
|||
#include "config.h" |
|||
#include <poll.h> |
|||
|
|||
/* Replacement poll which checks for memory leaks in middle of ccan/io loop. */ |
|||
int debug_poll(struct pollfd *fds, nfds_t nfds, int timeout); |
|||
|
|||
#endif /* LIGHTNING_COMMON_IO_DEBUG_H */ |
@ -1,10 +1,9 @@ |
|||
#ifndef LIGHTNING_COMMON_SUBDAEMON_H |
|||
#define LIGHTNING_COMMON_SUBDAEMON_H |
|||
#include "config.h" |
|||
#include <common/daemon.h> |
|||
|
|||
/* daemon_setup, but for subdaemons */ |
|||
void subdaemon_setup(int argc, char *argv[]); |
|||
|
|||
/* Shutdown for a valgrind-clean exit (frees everything) */ |
|||
void subdaemon_shutdown(void); |
|||
|
|||
#endif /* LIGHTNING_COMMON_SUBDAEMON_H */ |
|||
|
Loading…
Reference in new issue