Browse Source

lightningd: avoid errors on shutdown.

lightningd can crash on shutdown if it's in the middle of getchaintips;
we free the conn, the finished callback is called (process_chaintips),
and it reports that it received an empty result.

The simplest fix is to set a flag in the struct bitcoind destructor,
and avoid the callback.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 7 years ago
committed by Christian Decker
parent
commit
584b160cdc
  1. 13
      lightningd/bitcoind.c
  2. 3
      lightningd/bitcoind.h
  3. 4
      tests/test_lightningd.py

13
lightningd/bitcoind.c

@ -126,6 +126,11 @@ static void bcli_finished(struct io_conn *conn, struct bitcoin_cli *bcli)
*bcli->exitstatus = WEXITSTATUS(status);
bitcoind->req_running = false;
/* Don't continue if were only here because we were freed for shutdown */
if (bitcoind->shutdown)
return;
bcli->process(bcli);
next_bcli(bitcoind);
@ -448,6 +453,12 @@ void bitcoind_getblockhash_(struct bitcoind *bitcoind,
"getblockhash", str, NULL);
}
static void destroy_bitcoind(struct bitcoind *bitcoind)
{
/* Suppresses the callbacks from bcli_finished as we free conns. */
bitcoind->shutdown = true;
}
struct bitcoind *new_bitcoind(const tal_t *ctx, struct log *log)
{
struct bitcoind *bitcoind = tal(ctx, struct bitcoind);
@ -457,7 +468,9 @@ struct bitcoind *new_bitcoind(const tal_t *ctx, struct log *log)
bitcoind->datadir = NULL;
bitcoind->log = log;
bitcoind->req_running = false;
bitcoind->shutdown = false;
list_head_init(&bitcoind->pending);
tal_add_destructor(bitcoind, destroy_bitcoind);
return bitcoind;
}

3
lightningd/bitcoind.h

@ -36,6 +36,9 @@ struct bitcoind {
/* What network are we on? */
const struct chainparams *chainparams;
/* Ignore results, we're shutting down. */
bool shutdown;
};
struct bitcoind *new_bitcoind(const tal_t *ctx, struct log *log);

4
tests/test_lightningd.py

@ -244,6 +244,10 @@ class LightningDTests(BaseLightningDTests):
else:
lsrc.rpc.sendpay(to_json([routestep]), rhash, async=False)
def test_shutdown(self):
l1 = self.node_factory.get_node()
l1.rpc.stop()
def test_connect(self):
l1,l2 = self.connect()

Loading…
Cancel
Save