mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 21:35:11 +01:00
common/daemon: common routines for all daemons.
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>
This commit is contained in:
parent
8975fc2ceb
commit
1a4a59d221
@ -38,6 +38,7 @@ CHANNELD_COMMON_OBJS := \
|
||||
common/crypto_state.o \
|
||||
common/crypto_sync.o \
|
||||
common/cryptomsg.o \
|
||||
common/daemon.o \
|
||||
common/daemon_conn.o \
|
||||
common/derive_basepoints.o \
|
||||
common/dev_disconnect.o \
|
||||
@ -48,7 +49,6 @@ CHANNELD_COMMON_OBJS := \
|
||||
common/htlc_wire.o \
|
||||
common/initial_channel.o \
|
||||
common/initial_commit_tx.o \
|
||||
common/io_debug.o \
|
||||
common/keyset.o \
|
||||
common/key_derive.o \
|
||||
common/memleak.o \
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include <common/derive_basepoints.h>
|
||||
#include <common/dev_disconnect.h>
|
||||
#include <common/htlc_tx.h>
|
||||
#include <common/io_debug.h>
|
||||
#include <common/key_derive.h>
|
||||
#include <common/msg_queue.h>
|
||||
#include <common/peer_billboard.h>
|
||||
@ -2753,6 +2752,6 @@ int main(int argc, char *argv[])
|
||||
/* We only exit when shutdown is complete. */
|
||||
assert(shutdown_complete(peer));
|
||||
send_shutdown_complete(peer);
|
||||
subdaemon_shutdown();
|
||||
daemon_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ CLOSINGD_COMMON_OBJS := \
|
||||
common/crypto_state.o \
|
||||
common/crypto_sync.o \
|
||||
common/cryptomsg.o \
|
||||
common/daemon.o \
|
||||
common/daemon_conn.o \
|
||||
common/dev_disconnect.o \
|
||||
common/derive_basepoints.o \
|
||||
|
@ -577,7 +577,7 @@ int main(int argc, char *argv[])
|
||||
wire_sync_write(REQ_FD,
|
||||
take(towire_closing_complete(NULL, gossip_index)));
|
||||
tal_free(ctx);
|
||||
subdaemon_shutdown();
|
||||
daemon_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ COMMON_SRC_NOGEN := \
|
||||
common/crypto_state.c \
|
||||
common/crypto_sync.c \
|
||||
common/cryptomsg.c \
|
||||
common/daemon.c \
|
||||
common/daemon_conn.c \
|
||||
common/derive_basepoints.c \
|
||||
common/dev_disconnect.c \
|
||||
@ -19,7 +20,6 @@ COMMON_SRC_NOGEN := \
|
||||
common/htlc_wire.c \
|
||||
common/initial_channel.c \
|
||||
common/initial_commit_tx.c \
|
||||
common/io_debug.c \
|
||||
common/json.c \
|
||||
common/json_escaped.c \
|
||||
common/key_derive.c \
|
||||
|
111
common/daemon.c
Normal file
111
common/daemon.c
Normal file
@ -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);
|
||||
}
|
13
common/daemon.h
Normal file
13
common/daemon.h
Normal file
@ -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,7 +1,3 @@
|
||||
#include <backtrace-supported.h>
|
||||
#include <backtrace.h>
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/str/str.h>
|
||||
#include <common/dev_disconnect.h>
|
||||
#include <common/status.h>
|
||||
#include <common/subdaemon.h>
|
||||
@ -14,48 +10,20 @@
|
||||
#include <unistd.h>
|
||||
#include <wally_core.h>
|
||||
|
||||
#if BACKTRACE_SUPPORTED
|
||||
static struct backtrace_state *backtrace_state;
|
||||
|
||||
static int backtrace_status(void *unused UNUSED, uintptr_t pc,
|
||||
const char *filename, int lineno,
|
||||
const char *function)
|
||||
static void status_backtrace_print(const char *fmt, ...)
|
||||
{
|
||||
fprintf(stderr, "backtrace: %s:%d (%s) %p\n",
|
||||
filename, lineno, function, (void *)pc);
|
||||
status_trace("backtrace: %s:%d (%s) %p",
|
||||
filename, lineno, function, (void *)pc);
|
||||
return 0;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
status_vfmt(LOG_BROKEN, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void crashdump(int sig)
|
||||
static void status_backtrace_exit(void)
|
||||
{
|
||||
/* We do stderr first, since it's most reliable. */
|
||||
warnx("Fatal signal %d", sig);
|
||||
backtrace_print(backtrace_state, 0, stderr);
|
||||
|
||||
/* Now send to parent. */
|
||||
backtrace_full(backtrace_state, 0, backtrace_status, NULL, NULL);
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR, "FATAL SIGNAL %d", sig);
|
||||
status_failed(STATUS_FAIL_INTERNAL_ERROR, "FATAL SIGNAL");
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
#if DEVELOPER
|
||||
extern volatile bool debugger_connected;
|
||||
volatile bool debugger_connected;
|
||||
@ -68,18 +36,6 @@ void subdaemon_setup(int argc, char *argv[])
|
||||
exit(0);
|
||||
}
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
#if BACKTRACE_SUPPORTED
|
||||
backtrace_state = backtrace_create_state(argv[0], 0, NULL, NULL);
|
||||
crashlog_activate();
|
||||
#endif
|
||||
|
||||
/* We handle write returning errors! */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
secp256k1_ctx = wally_get_secp_context();
|
||||
|
||||
setup_tmpctx();
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (streq(argv[i], "--log-io"))
|
||||
logging_io = true;
|
||||
@ -100,10 +56,7 @@ void subdaemon_setup(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
daemon_setup(argv[0], status_backtrace_print, status_backtrace_exit);
|
||||
}
|
||||
|
||||
void subdaemon_shutdown(void)
|
||||
{
|
||||
tal_free(tmpctx);
|
||||
wally_cleanup(0);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -39,11 +39,11 @@ GOSSIPD_COMMON_OBJS := \
|
||||
common/crypto_state.o \
|
||||
common/crypto_sync.o \
|
||||
common/cryptomsg.o \
|
||||
common/daemon.o \
|
||||
common/daemon_conn.o \
|
||||
common/dev_disconnect.o \
|
||||
common/features.o \
|
||||
common/gen_status_wire.o \
|
||||
common/io_debug.o \
|
||||
common/msg_queue.o \
|
||||
common/ping.o \
|
||||
common/pseudorand.o \
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <common/cryptomsg.h>
|
||||
#include <common/daemon_conn.h>
|
||||
#include <common/features.h>
|
||||
#include <common/io_debug.h>
|
||||
#include <common/ping.h>
|
||||
#include <common/status.h>
|
||||
#include <common/subdaemon.h>
|
||||
@ -2118,7 +2117,6 @@ int main(int argc, char *argv[])
|
||||
struct daemon *daemon;
|
||||
|
||||
subdaemon_setup(argc, argv);
|
||||
io_poll_override(debug_poll);
|
||||
|
||||
daemon = tal(NULL, struct daemon);
|
||||
list_head_init(&daemon->peers);
|
||||
@ -2147,7 +2145,7 @@ int main(int argc, char *argv[])
|
||||
timer_expired(daemon, expired);
|
||||
}
|
||||
}
|
||||
subdaemon_shutdown();
|
||||
daemon_shutdown();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@ -21,12 +21,12 @@ LIGHTNINGD_HSM_OBJS := $(LIGHTNINGD_HSM_SRC:.c=.o)
|
||||
# Common source we use.
|
||||
HSMD_COMMON_OBJS := \
|
||||
common/bip32.o \
|
||||
common/daemon.o \
|
||||
common/daemon_conn.o \
|
||||
common/derive_basepoints.o \
|
||||
common/funding_tx.o \
|
||||
common/gen_status_wire.o \
|
||||
common/hash_u5.o \
|
||||
common/io_debug.o \
|
||||
common/key_derive.o \
|
||||
common/msg_queue.o \
|
||||
common/permute_tx.o \
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include <common/derive_basepoints.h>
|
||||
#include <common/funding_tx.h>
|
||||
#include <common/hash_u5.h>
|
||||
#include <common/io_debug.h>
|
||||
#include <common/key_derive.h>
|
||||
#include <common/status.h>
|
||||
#include <common/subdaemon.h>
|
||||
@ -829,7 +828,6 @@ int main(int argc, char *argv[])
|
||||
struct client *client;
|
||||
|
||||
subdaemon_setup(argc, argv);
|
||||
io_poll_override(debug_poll);
|
||||
|
||||
client = new_client(NULL, NULL, HSM_CAP_MASTER | HSM_CAP_SIGN_GOSSIP, handle_client, STDIN_FILENO);
|
||||
|
||||
@ -842,7 +840,7 @@ int main(int argc, char *argv[])
|
||||
/* When conn closes, everything is freed. */
|
||||
tal_steal(client->dc.conn, client);
|
||||
io_loop(NULL, NULL);
|
||||
subdaemon_shutdown();
|
||||
daemon_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ LIGHTNINGD_COMMON_OBJS := \
|
||||
common/channel_config.o \
|
||||
common/configdir.o \
|
||||
common/crypto_state.o \
|
||||
common/daemon.o \
|
||||
common/derive_basepoints.o \
|
||||
common/features.o \
|
||||
common/funding_tx.o \
|
||||
@ -28,7 +29,6 @@ LIGHTNINGD_COMMON_OBJS := \
|
||||
common/hash_u5.o \
|
||||
common/htlc_state.o \
|
||||
common/htlc_wire.o \
|
||||
common/io_debug.o \
|
||||
common/key_derive.o \
|
||||
common/json.o \
|
||||
common/json_escaped.o \
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <ccan/tal/grab_file/grab_file.h>
|
||||
#include <ccan/tal/path/path.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/io_debug.h>
|
||||
#include <common/daemon.h>
|
||||
#include <common/memleak.h>
|
||||
#include <common/timeout.h>
|
||||
#include <common/utils.h>
|
||||
@ -277,21 +277,8 @@ int main(int argc, char *argv[])
|
||||
bool newdir;
|
||||
u32 first_blocknum;
|
||||
|
||||
err_set_progname(argv[0]);
|
||||
|
||||
#if DEVELOPER
|
||||
/* Suppresses backtrace (breaks valgrind) */
|
||||
if (!getenv("LIGHTNINGD_DEV_NO_BACKTRACE"))
|
||||
backtrace_state = backtrace_create_state(argv[0], 0, NULL, NULL);
|
||||
#else
|
||||
backtrace_state = backtrace_create_state(argv[0], 0, NULL, NULL);
|
||||
#endif
|
||||
|
||||
daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit);
|
||||
ld = new_lightningd(NULL);
|
||||
secp256k1_ctx = wally_get_secp_context();
|
||||
setup_tmpctx();
|
||||
|
||||
io_poll_override(debug_poll);
|
||||
|
||||
/* Figure out where our daemons are first. */
|
||||
ld->daemon_dir = find_daemon_dir(ld, argv[0]);
|
||||
@ -399,7 +386,7 @@ int main(int argc, char *argv[])
|
||||
begin_topology(ld->topology);
|
||||
|
||||
/* Activate crash log now we're not reporting startup failures. */
|
||||
crashlog_activate(argv[0], ld->log);
|
||||
crashlog = ld->log;
|
||||
|
||||
for (;;) {
|
||||
struct timer *expired;
|
||||
@ -426,7 +413,6 @@ int main(int argc, char *argv[])
|
||||
#if DEVELOPER
|
||||
memleak_cleanup();
|
||||
#endif
|
||||
take_cleanup();
|
||||
wally_cleanup(0);
|
||||
daemon_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
127
lightningd/log.c
127
lightningd/log.c
@ -23,6 +23,9 @@
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/* Once we're up and running, this is set up. */
|
||||
struct log *crashlog;
|
||||
|
||||
struct log_entry {
|
||||
struct list_node list;
|
||||
struct timeabs time;
|
||||
@ -464,86 +467,19 @@ void opt_register_logging(struct lightningd *ld)
|
||||
"log to file instead of stdout");
|
||||
}
|
||||
|
||||
#if BACKTRACE_SUPPORTED
|
||||
static int log_backtrace(void *log, uintptr_t pc,
|
||||
const char *filename, int lineno,
|
||||
const char *function)
|
||||
void log_backtrace_print(const char *fmt, ...)
|
||||
{
|
||||
log_broken(log, "backtrace: %s:%u (%s) %p",
|
||||
filename, lineno, function, (void *)pc);
|
||||
return 0;
|
||||
va_list ap;
|
||||
|
||||
if (!crashlog)
|
||||
return;
|
||||
|
||||
va_start(ap, fmt);
|
||||
logv(crashlog, LOG_BROKEN, fmt, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
static void log_backtrace_error(void *log, const char *msg,
|
||||
int errnum)
|
||||
{
|
||||
log_broken(log, "error getting backtrace: %s (%d)",
|
||||
msg, errnum);
|
||||
}
|
||||
|
||||
static struct log *crashlog;
|
||||
|
||||
/* FIXME: Dump peer logs! */
|
||||
static void log_crash(int sig)
|
||||
{
|
||||
const char *logfile = NULL;
|
||||
|
||||
if (sig) {
|
||||
log_broken(crashlog, "FATAL SIGNAL %i RECEIVED", sig);
|
||||
if (backtrace_state)
|
||||
backtrace_full(backtrace_state, 0, log_backtrace, log_backtrace_error,
|
||||
crashlog);
|
||||
}
|
||||
|
||||
if (crashlog->lr->print == log_to_stdout) {
|
||||
int fd;
|
||||
|
||||
/* We expect to be in config dir. */
|
||||
logfile = "crash.log";
|
||||
fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600);
|
||||
if (fd < 0) {
|
||||
logfile = "/tmp/lightning-crash.log";
|
||||
fd = open(logfile, O_WRONLY|O_CREAT, 0600);
|
||||
}
|
||||
|
||||
/* Dump entire log. */
|
||||
if (fd >= 0) {
|
||||
log_dump_to_file(fd, crashlog->lr);
|
||||
close(fd);
|
||||
} else
|
||||
logfile = NULL;
|
||||
}
|
||||
|
||||
if (sig) {
|
||||
fprintf(stderr, "Fatal signal %d. ", sig);
|
||||
if (backtrace_state)
|
||||
backtrace_print(backtrace_state, 0, stderr);
|
||||
}
|
||||
if (logfile)
|
||||
fprintf(stderr, "Log dumped in %s", logfile);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void crashlog_activate(const char *argv0 UNUSED, struct log *log)
|
||||
{
|
||||
#if BACKTRACE_SUPPORTED
|
||||
struct sigaction sa;
|
||||
crashlog = log;
|
||||
|
||||
sa.sa_handler = log_crash;
|
||||
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
|
||||
}
|
||||
|
||||
void log_dump_to_file(int fd, const struct log_book *lr)
|
||||
static void log_dump_to_file(int fd, const struct log_book *lr)
|
||||
{
|
||||
const struct log_entry *i;
|
||||
char buf[100];
|
||||
@ -571,6 +507,34 @@ void log_dump_to_file(int fd, const struct log_book *lr)
|
||||
write_all(fd, "\n\n", strlen("\n\n"));
|
||||
}
|
||||
|
||||
/* FIXME: Dump peer logs! */
|
||||
void log_backtrace_exit(void)
|
||||
{
|
||||
if (!crashlog)
|
||||
return;
|
||||
|
||||
/* If we're not already pointing at a log file, make one */
|
||||
if (crashlog->lr->print == log_to_stdout) {
|
||||
const char *logfile = NULL;
|
||||
int fd;
|
||||
|
||||
/* We expect to be in config dir. */
|
||||
logfile = "crash.log";
|
||||
fd = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0600);
|
||||
if (fd < 0) {
|
||||
logfile = "/tmp/lightning-crash.log";
|
||||
fd = open(logfile, O_WRONLY|O_CREAT, 0600);
|
||||
}
|
||||
|
||||
/* Dump entire log. */
|
||||
if (fd >= 0) {
|
||||
log_dump_to_file(fd, crashlog->lr);
|
||||
close(fd);
|
||||
fprintf(stderr, "Log dumped in %s\n", logfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void fatal(const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
@ -580,15 +544,12 @@ void fatal(const char *fmt, ...)
|
||||
fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
|
||||
#if BACKTRACE_SUPPORTED
|
||||
/* Early on, we just dump errors to stderr. */
|
||||
if (crashlog) {
|
||||
if (!crashlog)
|
||||
exit(1);
|
||||
|
||||
va_start(ap, fmt);
|
||||
logv(crashlog, LOG_BROKEN, fmt, ap);
|
||||
va_end(ap);
|
||||
log_crash(0);
|
||||
}
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -87,15 +87,17 @@ void log_each_line_(const struct log_book *lr,
|
||||
void *arg);
|
||||
|
||||
|
||||
void log_dump_to_file(int fd, const struct log_book *lr);
|
||||
void opt_register_logging(struct lightningd *ld);
|
||||
void crashlog_activate(const char *argv0, struct log *log);
|
||||
|
||||
char *arg_log_to_file(const char *arg, struct lightningd *ld);
|
||||
|
||||
/* Before the crashlog is activated, just prints to stderr. */
|
||||
/* Once this is set, we dump fatal with a backtrace to this log */
|
||||
extern struct log *crashlog;
|
||||
void NORETURN PRINTF_FMT(1,2) fatal(const char *fmt, ...);
|
||||
|
||||
void log_backtrace_print(const char *fmt, ...);
|
||||
void log_backtrace_exit(void);
|
||||
|
||||
/* Adds an array showing log entries */
|
||||
void json_add_log(struct json_result *result,
|
||||
const struct log_book *lr, enum log_level minlevel);
|
||||
|
@ -10,9 +10,15 @@ void activate_peers(struct lightningd *ld UNNEEDED)
|
||||
/* Generated stub for begin_topology */
|
||||
void begin_topology(struct chain_topology *topo UNNEEDED)
|
||||
{ fprintf(stderr, "begin_topology called!\n"); abort(); }
|
||||
/* Generated stub for crashlog_activate */
|
||||
void crashlog_activate(const char *argv0 UNNEEDED, struct log *log UNNEEDED)
|
||||
{ fprintf(stderr, "crashlog_activate called!\n"); abort(); }
|
||||
/* Could not find declaration for crashlog */
|
||||
/* Generated stub for daemon_setup */
|
||||
void daemon_setup(const char *argv0 UNNEEDED,
|
||||
void (*backtrace_print)(const char *fmt UNNEEDED, ...) UNNEEDED,
|
||||
void (*backtrace_exit)(void))
|
||||
{ fprintf(stderr, "daemon_setup called!\n"); abort(); }
|
||||
/* Generated stub for daemon_shutdown */
|
||||
void daemon_shutdown(void)
|
||||
{ fprintf(stderr, "daemon_shutdown called!\n"); abort(); }
|
||||
/* Generated stub for db_begin_transaction_ */
|
||||
void db_begin_transaction_(struct db *db UNNEEDED, const char *location UNNEEDED)
|
||||
{ fprintf(stderr, "db_begin_transaction_ called!\n"); abort(); }
|
||||
@ -28,9 +34,6 @@ s64 db_get_intvar(struct db *db UNNEEDED, char *varname UNNEEDED, s64 defval UNN
|
||||
/* Generated stub for db_reopen_after_fork */
|
||||
void db_reopen_after_fork(struct db *db UNNEEDED)
|
||||
{ fprintf(stderr, "db_reopen_after_fork called!\n"); abort(); }
|
||||
/* Generated stub for debug_poll */
|
||||
int debug_poll(struct pollfd *fds UNNEEDED, nfds_t nfds UNNEEDED, int timeout UNNEEDED)
|
||||
{ fprintf(stderr, "debug_poll called!\n"); abort(); }
|
||||
/* Generated stub for fatal */
|
||||
void fatal(const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "fatal called!\n"); abort(); }
|
||||
@ -56,6 +59,12 @@ struct json_escaped *json_escape(const tal_t *ctx UNNEEDED, const char *str TAKE
|
||||
void log_(struct log *log UNNEEDED, enum log_level level UNNEEDED, const char *fmt UNNEEDED, ...)
|
||||
|
||||
{ fprintf(stderr, "log_ called!\n"); abort(); }
|
||||
/* Generated stub for log_backtrace_exit */
|
||||
void log_backtrace_exit(void)
|
||||
{ fprintf(stderr, "log_backtrace_exit called!\n"); abort(); }
|
||||
/* Generated stub for log_backtrace_print */
|
||||
void log_backtrace_print(const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "log_backtrace_print called!\n"); abort(); }
|
||||
/* Generated stub for new_log */
|
||||
struct log *new_log(const tal_t *ctx UNNEEDED, struct log_book *record UNNEEDED, const char *fmt UNNEEDED, ...)
|
||||
{ fprintf(stderr, "new_log called!\n"); abort(); }
|
||||
@ -141,6 +150,8 @@ char *opt_subd_dev_disconnect(const char *optarg UNNEEDED, struct lightningd *ld
|
||||
{ fprintf(stderr, "opt_subd_dev_disconnect called!\n"); abort(); }
|
||||
#endif
|
||||
|
||||
struct log *crashlog;
|
||||
|
||||
#undef main
|
||||
int main(int argc UNUSED, char *argv[] UNUSED)
|
||||
{
|
||||
|
@ -47,6 +47,7 @@ $(LIGHTNINGD_ONCHAIN_OBJS): $(LIGHTNINGD_HEADERS)
|
||||
|
||||
# Common source we use.
|
||||
ONCHAIND_COMMON_OBJS := \
|
||||
common/daemon.o \
|
||||
common/daemon_conn.o \
|
||||
common/derive_basepoints.o \
|
||||
common/dev_disconnect.o \
|
||||
|
@ -2315,7 +2315,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
/* We're done! */
|
||||
tal_free(ctx);
|
||||
subdaemon_shutdown();
|
||||
daemon_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -40,6 +40,7 @@ OPENINGD_COMMON_OBJS := \
|
||||
common/crypto_state.o \
|
||||
common/crypto_sync.o \
|
||||
common/cryptomsg.o \
|
||||
common/daemon.o \
|
||||
common/daemon_conn.o \
|
||||
common/derive_basepoints.o \
|
||||
common/dev_disconnect.o \
|
||||
|
@ -776,7 +776,7 @@ int main(int argc, char *argv[])
|
||||
status_trace("Sent %s with fd",
|
||||
opening_wire_type_name(fromwire_peektype(msg)));
|
||||
tal_free(state);
|
||||
subdaemon_shutdown();
|
||||
daemon_shutdown();
|
||||
return 0;
|
||||
}
|
||||
#endif /* TESTING */
|
||||
|
Loading…
Reference in New Issue
Block a user