diff --git a/daemon/bitcoind.c b/daemon/bitcoind.c index 6b88acb16..228a09c76 100644 --- a/daemon/bitcoind.c +++ b/daemon/bitcoind.c @@ -36,6 +36,7 @@ static char **gather_args(const tal_t *ctx, const char *cmd, va_list ap) } struct bitcoin_cli { + struct list_node list; struct lightningd_state *dstate; int fd; pid_t pid; @@ -65,9 +66,12 @@ static struct io_plan *output_init(struct io_conn *conn, struct bitcoin_cli *bcl return read_more(conn, bcli); } +static void next_bcli(struct lightningd_state *dstate); + static void bcli_finished(struct io_conn *conn, struct bitcoin_cli *bcli) { int ret, status; + struct lightningd_state *dstate = bcli->dstate; /* FIXME: If we waited for SIGCHILD, this could never hang! */ ret = waitpid(bcli->pid, &status, 0); @@ -86,9 +90,35 @@ static void bcli_finished(struct io_conn *conn, struct bitcoin_cli *bcli) bcli->args[0], bcli->args[1], WEXITSTATUS(status), (int)bcli->output_bytes, bcli->output); - assert(bcli->dstate->bitcoind_in_progress); - bcli->dstate->bitcoind_in_progress--; + log_debug(dstate->base_log, "reaped %u: %s", ret, bcli->args[1]); + dstate->bitcoin_req_running = false; bcli->process(bcli); + + next_bcli(dstate); +} + +static void next_bcli(struct lightningd_state *dstate) +{ + struct bitcoin_cli *bcli; + struct io_conn *conn; + + if (dstate->bitcoin_req_running) + return; + + bcli = list_pop(&dstate->bitcoin_req, struct bitcoin_cli, list); + if (!bcli) + return; + + log_debug(bcli->dstate->base_log, "starting: %s", bcli->args[1]); + + bcli->pid = pipecmdarr(&bcli->fd, NULL, &bcli->fd, bcli->args); + if (bcli->pid < 0) + fatal("%s exec failed: %s", bcli->args[0], strerror(errno)); + + dstate->bitcoin_req_running = true; + conn = io_new_conn(dstate, bcli->fd, output_init, bcli); + tal_steal(conn, bcli); + io_set_finish(conn, bcli_finished, bcli); } static void @@ -99,7 +129,6 @@ start_bitcoin_cli(struct lightningd_state *dstate, { va_list ap; struct bitcoin_cli *bcli = tal(dstate, struct bitcoin_cli); - struct io_conn *conn; bcli->dstate = dstate; bcli->process = process; @@ -109,14 +138,8 @@ start_bitcoin_cli(struct lightningd_state *dstate, bcli->args = gather_args(bcli, cmd, ap); va_end(ap); - bcli->pid = pipecmdarr(&bcli->fd, NULL, &bcli->fd, bcli->args); - if (bcli->pid < 0) - fatal("%s exec failed: %s", bcli->args[0], strerror(errno)); - - conn = io_new_conn(dstate, bcli->fd, output_init, bcli); - tal_steal(conn, bcli); - dstate->bitcoind_in_progress++; - io_set_finish(conn, bcli_finished, bcli); + list_add_tail(&dstate->bitcoin_req, &bcli->list); + next_bcli(dstate); } static void process_importaddress(struct bitcoin_cli *bcli) diff --git a/daemon/lightningd.c b/daemon/lightningd.c index a67bfe9f1..55986dd0d 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -127,7 +127,8 @@ static struct lightningd_state *lightningd_state(void) dstate->secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY | SECP256K1_CONTEXT_SIGN); default_config(&dstate->config); - dstate->bitcoind_in_progress = 0; + list_head_init(&dstate->bitcoin_req); + dstate->bitcoin_req_running = false; return dstate; } diff --git a/daemon/lightningd.h b/daemon/lightningd.h index dfe63039e..782e4f4a2 100644 --- a/daemon/lightningd.h +++ b/daemon/lightningd.h @@ -62,11 +62,12 @@ struct lightningd_state { /* This is us. */ struct pubkey id; - /* Number of bitcoind commands outstanding. */ - unsigned int bitcoind_in_progress; - /* Transactions/txos we are watching. */ struct txwatch_hash txwatches; struct txowatch_hash txowatches; + + /* Outstanding bitcoind requests. */ + struct list_head bitcoin_req; + bool bitcoin_req_running; }; #endif /* LIGHTNING_DAEMON_LIGHTNING_H */ diff --git a/daemon/watch.c b/daemon/watch.c index 7a95bc465..c4496effe 100644 --- a/daemon/watch.c +++ b/daemon/watch.c @@ -213,10 +213,9 @@ static struct timeout watch_timeout; static void start_poll_transactions(struct lightningd_state *dstate) { - if (dstate->bitcoind_in_progress != 0) { + if (!list_empty(&dstate->bitcoin_req)) { log_unusual(dstate->base_log, - "Delaying start poll: %u commands in progress", - dstate->bitcoind_in_progress); + "Delaying start poll: commands in progress"); } else bitcoind_poll_transactions(dstate, watched_transaction); refresh_timeout(dstate, &watch_timeout);