diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 1f0b70eed..31db45c43 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -237,11 +237,12 @@ static void init_txfilter(struct wallet *w, struct txfilter *filter) } } -static void daemonize_but_keep_dir(void) +static void daemonize_but_keep_dir(struct lightningd *ld) { /* daemonize moves us into /, but we want to be here */ const char *cwd = path_cwd(NULL); + db_close_for_fork(ld->wallet->db); if (!cwd) fatal("Could not get current directory: %s", strerror(errno)); if (!daemonize()) @@ -252,6 +253,7 @@ static void daemonize_but_keep_dir(void) fatal("Could not return to directory %s: %s", cwd, strerror(errno)); + db_reopen_after_fork(ld->wallet->db); tal_free(cwd); } @@ -382,7 +384,7 @@ int main(int argc, char *argv[]) /* Now we're about to start, become daemon if desired. */ if (ld->daemon) - daemonize_but_keep_dir(); + daemonize_but_keep_dir(ld); /* Mark ourselves live. */ log_info(ld->log, "Server started with public key %s, alias %s (color #%s) and lightningd %s", diff --git a/lightningd/test/run-find_my_path.c b/lightningd/test/run-find_my_path.c index 1dc98c9fd..a5b30752d 100644 --- a/lightningd/test/run-find_my_path.c +++ b/lightningd/test/run-find_my_path.c @@ -16,12 +16,18 @@ void crashlog_activate(const char *argv0 UNNEEDED, struct log *log UNNEEDED) /* 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(); } +/* Generated stub for db_close_for_fork */ +void db_close_for_fork(struct db *db UNNEEDED) +{ fprintf(stderr, "db_close_for_fork called!\n"); abort(); } /* Generated stub for db_commit_transaction */ void db_commit_transaction(struct db *db UNNEEDED) { fprintf(stderr, "db_commit_transaction called!\n"); abort(); } /* Generated stub for db_get_intvar */ s64 db_get_intvar(struct db *db UNNEEDED, char *varname UNNEEDED, s64 defval UNNEEDED) { fprintf(stderr, "db_get_intvar called!\n"); abort(); } +/* 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(); } @@ -35,7 +41,7 @@ void free_htlcs(struct lightningd *ld UNNEEDED, const struct channel *channel UN void gossip_init(struct lightningd *ld UNNEEDED) { fprintf(stderr, "gossip_init called!\n"); abort(); } /* Generated stub for handle_opts */ -bool handle_opts(struct lightningd *ld UNNEEDED, int argc UNNEEDED, char *argv[] UNUSED) +bool handle_opts(struct lightningd *ld UNNEEDED, int argc UNNEEDED, char *argv[]) { fprintf(stderr, "handle_opts called!\n"); abort(); } /* Generated stub for hash_htlc_key */ size_t hash_htlc_key(const struct htlc_key *htlc_key UNNEEDED) @@ -78,7 +84,7 @@ void subd_shutdown(struct subd *subd UNNEEDED, unsigned int seconds UNNEEDED) void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED) { fprintf(stderr, "timer_expired called!\n"); abort(); } /* Generated stub for txfilter_add_derkey */ -void txfilter_add_derkey(struct txfilter *filter UNNEEDED, u8 derkey[PUBKEY_DER_LEN] UNUSED) +void txfilter_add_derkey(struct txfilter *filter UNNEEDED, u8 derkey[PUBKEY_DER_LEN]) { fprintf(stderr, "txfilter_add_derkey called!\n"); abort(); } /* Generated stub for txfilter_new */ struct txfilter *txfilter_new(const tal_t *ctx UNNEEDED) diff --git a/wallet/db.c b/wallet/db.c index 22da48311..9083304ff 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -432,6 +432,28 @@ struct db *db_setup(const tal_t *ctx, struct log *log) return db; } +void db_close_for_fork(struct db *db) +{ + /* https://www.sqlite.org/faq.html#q6 + * + * Under Unix, you should not carry an open SQLite database across a + * fork() system call into the child process. */ + if (sqlite3_close(db->sql) != SQLITE_OK) + fatal("sqlite3_close: %s", sqlite3_errmsg(db->sql)); + db->sql = NULL; +} + +void db_reopen_after_fork(struct db *db) +{ + int err = sqlite3_open_v2(db->filename, &db->sql, + SQLITE_OPEN_READWRITE, NULL); + + if (err != SQLITE_OK) { + fatal("failed to re-open database %s: %s", db->filename, + sqlite3_errstr(err)); + } +} + s64 db_get_intvar(struct db *db, char *varname, s64 defval) { int err; diff --git a/wallet/db.h b/wallet/db.h index 2176b5372..7514cd7b7 100644 --- a/wallet/db.h +++ b/wallet/db.h @@ -113,6 +113,10 @@ bool db_exec_prepared_mayfail_(const char *caller, struct db *db, sqlite3_stmt *stmt); +/* Do not keep db open across a fork: needed for --daemon */ +void db_close_for_fork(struct db *db); +void db_reopen_after_fork(struct db *db); + #define sqlite3_column_arr(ctx, stmt, col, type) \ ((type *)sqlite3_column_arr_((ctx), (stmt), (col), \ sizeof(type), TAL_LABEL(type, "[]"), \ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 34e22ae1e..16099d9bd 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -230,9 +230,6 @@ void log_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, ...) void log_io(struct log *log UNNEEDED, enum log_level dir UNNEEDED, const char *comment UNNEEDED, const void *data UNNEEDED, size_t len UNNEEDED) { fprintf(stderr, "log_io called!\n"); abort(); } -/* Generated stub for logv_add */ -void logv_add(struct log *log UNNEEDED, const char *fmt UNNEEDED, va_list ap UNNEEDED) -{ fprintf(stderr, "logv_add called!\n"); abort(); } /* Generated stub for new_json_result */ struct json_result *new_json_result(const tal_t *ctx UNNEEDED) { fprintf(stderr, "new_json_result called!\n"); abort(); }