From a2d4e09b80333d848888c1315441223aacf9ead6 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Thu, 28 Sep 2017 13:08:05 +0930 Subject: [PATCH] bitcoind: wait for startup. We don't hit this in testing, since we wait for startup already. Hacking tests to avoid that, I tested this code by hand. Signed-off-by: Rusty Russell --- lightningd/bitcoind.c | 59 +++++++++++++++++++++++++++++++++++++- lightningd/bitcoind.h | 2 ++ lightningd/chaintopology.c | 3 ++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lightningd/bitcoind.c b/lightningd/bitcoind.c index 745dae796..2bd99d359 100644 --- a/lightningd/bitcoind.c +++ b/lightningd/bitcoind.c @@ -24,7 +24,7 @@ char *bitcoin_datadir; -static char **gather_args(struct bitcoind *bitcoind, +static char **gather_args(const struct bitcoind *bitcoind, const tal_t *ctx, const char *cmd, va_list ap) { size_t n = 0; @@ -459,6 +459,63 @@ static void destroy_bitcoind(struct bitcoind *bitcoind) bitcoind->shutdown = true; } +static char **cmdarr(const tal_t *ctx, const struct bitcoind *bitcoind, + const char *cmd, ...) +{ + va_list ap; + char **args; + + va_start(ap, cmd); + args = gather_args(bitcoind, ctx, cmd, ap); + va_end(ap); + return args; +} + +void wait_for_bitcoind(struct bitcoind *bitcoind) +{ + int from, ret, status; + pid_t child; + char **cmd = cmdarr(bitcoind, bitcoind, "echo", NULL); + char *output; + bool printed = false; + + for (;;) { + child = pipecmdarr(&from, NULL, &from, cmd); + if (child < 0) + fatal("%s exec failed: %s", cmd[0], strerror(errno)); + + output = grab_fd(cmd, from); + if (!output) + fatal("Reading from %s failed: %s", + cmd[0], strerror(errno)); + + ret = waitpid(child, &status, 0); + if (ret != child) + fatal("Waiting for %s: %s", cmd[0], strerror(errno)); + if (!WIFEXITED(status)) + fatal("Death of %s: signal %i", + cmd[0], WTERMSIG(status)); + + if (WEXITSTATUS(status) == 0) + break; + + /* bitcoin/src/rpc/protocol.h: + * RPC_IN_WARMUP = -28, //!< Client still warming up + */ + if (WEXITSTATUS(status) != 28) + fatal("%s exited with code %i: %s", + cmd[0], WEXITSTATUS(status), output); + + if (!printed) { + log_unusual(bitcoind->log, + "Waiting for bitcoind to warm up..."); + printed = true; + } + sleep(1); + } + tal_free(cmd); +} + struct bitcoind *new_bitcoind(const tal_t *ctx, struct log *log) { struct bitcoind *bitcoind = tal(ctx, struct bitcoind); diff --git a/lightningd/bitcoind.h b/lightningd/bitcoind.h index 69a8046c7..6b8c42b24 100644 --- a/lightningd/bitcoind.h +++ b/lightningd/bitcoind.h @@ -43,6 +43,8 @@ struct bitcoind { struct bitcoind *new_bitcoind(const tal_t *ctx, struct log *log); +void wait_for_bitcoind(struct bitcoind *bitcoind); + void bitcoind_estimate_fee_(struct bitcoind *bitcoind, void (*cb)(struct bitcoind *bitcoind, u64, void *), diff --git a/lightningd/chaintopology.c b/lightningd/chaintopology.c index 8ff5777fb..f4c7fe4b5 100644 --- a/lightningd/chaintopology.c +++ b/lightningd/chaintopology.c @@ -572,6 +572,9 @@ void setup_topology(struct chain_topology *topo, topo->poll_time = poll_time; topo->first_blocknum = first_peer_block; + /* Make sure bitcoind is started, and ready */ + wait_for_bitcoind(topo->bitcoind); + bitcoind_getblockcount(topo->bitcoind, get_init_blockhash, topo); tal_add_destructor(topo, destroy_outgoing_txs);