From 89c3541c838cf9e252d6acfb0d12b2769e52fd4e Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 1 Sep 2021 14:05:15 +0930 Subject: [PATCH] lightningd: disable topology timers on shutdown. Not necessary yet, but it will be once shutdown starts waiting for plugins to respond: we don't want these to try to access the bcli plugin once it's freed. Signed-off-by: Rusty Russell --- lightningd/bitcoind.h | 3 ++ lightningd/chaintopology.c | 43 ++++++++++++++++++--------- lightningd/chaintopology.h | 5 ++++ lightningd/lightningd.c | 3 ++ lightningd/test/run-find_my_abspath.c | 3 ++ 5 files changed, 43 insertions(+), 14 deletions(-) diff --git a/lightningd/bitcoind.h b/lightningd/bitcoind.h index 8fb275e34..d17a28605 100644 --- a/lightningd/bitcoind.h +++ b/lightningd/bitcoind.h @@ -32,6 +32,9 @@ struct bitcoind { /* Ignore results, we're shutting down. */ bool shutdown; + /* Timer if we're waiting for it to warm up. */ + struct oneshot *checkchain_timer; + struct list_head pending_getfilteredblock; /* Map each method to a plugin, so we can have multiple plugins diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 67fbb549f..9b3b7a657 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -46,10 +46,10 @@ static void maybe_completed_init(struct chain_topology *topo) static void next_topology_timer(struct chain_topology *topo) { - /* This takes care of its own lifetime. */ - notleak(new_reltimer(topo->ld->timers, topo, - time_from_sec(topo->poll_seconds), - try_extend_tip, topo)); + assert(!topo->extend_timer); + topo->extend_timer = new_reltimer(topo->ld->timers, topo, + time_from_sec(topo->poll_seconds), + try_extend_tip, topo); } static bool we_broadcast(const struct chain_topology *topo, @@ -437,6 +437,7 @@ static void update_feerates(struct bitcoind *bitcoind, static void start_fee_estimate(struct chain_topology *topo) { + topo->updatefee_timer = NULL; /* Once per new block head, update fee estimates. */ bitcoind_estimate_fees(topo->bitcoind, NUM_FEERATES, update_feerates, topo); @@ -582,10 +583,10 @@ AUTODATA(json_command, &parse_feerate_command); static void next_updatefee_timer(struct chain_topology *topo) { - /* This takes care of its own lifetime. */ - notleak(new_reltimer(topo->ld->timers, topo, - time_from_sec(topo->poll_seconds), - start_fee_estimate, topo)); + assert(!topo->updatefee_timer); + topo->updatefee_timer = new_reltimer(topo->ld->timers, topo, + time_from_sec(topo->poll_seconds), + start_fee_estimate, topo); } struct sync_waiter { @@ -935,6 +936,7 @@ static void get_new_block(struct bitcoind *bitcoind, static void try_extend_tip(struct chain_topology *topo) { + topo->extend_timer = NULL; bitcoind_getrawblockbyheight(topo->bitcoind, topo->tip->height + 1, get_new_block, topo); } @@ -1144,15 +1146,18 @@ check_chain(struct bitcoind *bitcoind, const char *chain, return; } - notleak(new_reltimer(bitcoind->ld->timers, bitcoind, - /* Be 4x more aggressive in this case. */ - time_divide(time_from_sec(bitcoind->ld->topology - ->poll_seconds), 4), - retry_check_chain, bitcoind->ld->topology)); - } + assert(!bitcoind->checkchain_timer); + bitcoind->checkchain_timer + = new_reltimer(bitcoind->ld->timers, bitcoind, + /* Be 4x more aggressive in this case. */ + time_divide(time_from_sec(bitcoind->ld->topology + ->poll_seconds), 4), + retry_check_chain, bitcoind->ld->topology); +} static void retry_check_chain(struct chain_topology *topo) { + topo->bitcoind->checkchain_timer = NULL; bitcoind_getchaininfo(topo->bitcoind, false, check_chain, topo); } @@ -1171,6 +1176,7 @@ void setup_topology(struct chain_topology *topo, log_debug(topo->ld->log, "All Bitcoin plugin commands registered"); /* Sanity checks, then topology initialization. */ + topo->bitcoind->checkchain_timer = NULL; bitcoind_getchaininfo(topo->bitcoind, true, check_chain, topo); tal_add_destructor(topo, destroy_chain_topology); @@ -1185,3 +1191,12 @@ void begin_topology(struct chain_topology *topo) { try_extend_tip(topo); } + +void stop_topology(struct chain_topology *topo) +{ + /* Remove timers while we're cleaning up plugins. */ + tal_free(topo->bitcoind->checkchain_timer); + tal_free(topo->extend_timer); + tal_free(topo->updatefee_timer); +} + diff --git a/lightningd/chaintopology.h b/lightningd/chaintopology.h index 99c75c340..e824eb85e 100644 --- a/lightningd/chaintopology.h +++ b/lightningd/chaintopology.h @@ -113,6 +113,9 @@ struct chain_topology { /* The bitcoind. */ struct bitcoind *bitcoind; + /* Timers we're running. */ + struct oneshot *extend_timer, *updatefee_timer; + /* Bitcoin transactions we're broadcasting */ struct list_head outgoing_txs; @@ -195,6 +198,8 @@ void setup_topology(struct chain_topology *topology, void begin_topology(struct chain_topology *topo); +void stop_topology(struct chain_topology *topo); + struct txlocator *locate_tx(const void *ctx, const struct chain_topology *topo, const struct bitcoin_txid *txid); static inline bool topology_synced(const struct chain_topology *topo) diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c index 126908698..9282d9eab 100644 --- a/lightningd/lightningd.c +++ b/lightningd/lightningd.c @@ -1141,6 +1141,9 @@ int main(int argc, char *argv[]) stop_response = tal_steal(NULL, ld->stop_response); } + /* Stop topology callbacks. */ + stop_topology(ld->topology); + /* We're not going to collect our children. */ remove_sigchild_handler(); shutdown_subdaemons(ld); diff --git a/lightningd/test/run-find_my_abspath.c b/lightningd/test/run-find_my_abspath.c index 6fc6d46c7..4dde6dbf4 100644 --- a/lightningd/test/run-find_my_abspath.c +++ b/lightningd/test/run-find_my_abspath.c @@ -205,6 +205,9 @@ void setup_color_and_alias(struct lightningd *ld UNNEEDED) void setup_topology(struct chain_topology *topology UNNEEDED, u32 min_blockheight UNNEEDED, u32 max_blockheight UNNEEDED) { fprintf(stderr, "setup_topology called!\n"); abort(); } +/* Generated stub for stop_topology */ +void stop_topology(struct chain_topology *topo UNNEEDED) +{ fprintf(stderr, "stop_topology called!\n"); abort(); } /* Generated stub for timer_expired */ void timer_expired(tal_t *ctx UNNEEDED, struct timer *timer UNNEEDED) { fprintf(stderr, "timer_expired called!\n"); abort(); }