Browse Source

bitcoind: serialize requests.

bitcoind has a limit of 16 requests at once, by default, so our simplest
solution is to serialize them.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
ppa-0.6.1
Rusty Russell 9 years ago
parent
commit
5b9f8d8bbd
  1. 45
      daemon/bitcoind.c
  2. 3
      daemon/lightningd.c
  3. 7
      daemon/lightningd.h
  4. 5
      daemon/watch.c

45
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 bitcoin_cli {
struct list_node list;
struct lightningd_state *dstate; struct lightningd_state *dstate;
int fd; int fd;
pid_t pid; 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); 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) static void bcli_finished(struct io_conn *conn, struct bitcoin_cli *bcli)
{ {
int ret, status; int ret, status;
struct lightningd_state *dstate = bcli->dstate;
/* FIXME: If we waited for SIGCHILD, this could never hang! */ /* FIXME: If we waited for SIGCHILD, this could never hang! */
ret = waitpid(bcli->pid, &status, 0); 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), bcli->args[0], bcli->args[1], WEXITSTATUS(status),
(int)bcli->output_bytes, bcli->output); (int)bcli->output_bytes, bcli->output);
assert(bcli->dstate->bitcoind_in_progress); log_debug(dstate->base_log, "reaped %u: %s", ret, bcli->args[1]);
bcli->dstate->bitcoind_in_progress--; dstate->bitcoin_req_running = false;
bcli->process(bcli); 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 static void
@ -99,7 +129,6 @@ start_bitcoin_cli(struct lightningd_state *dstate,
{ {
va_list ap; va_list ap;
struct bitcoin_cli *bcli = tal(dstate, struct bitcoin_cli); struct bitcoin_cli *bcli = tal(dstate, struct bitcoin_cli);
struct io_conn *conn;
bcli->dstate = dstate; bcli->dstate = dstate;
bcli->process = process; bcli->process = process;
@ -109,14 +138,8 @@ start_bitcoin_cli(struct lightningd_state *dstate,
bcli->args = gather_args(bcli, cmd, ap); bcli->args = gather_args(bcli, cmd, ap);
va_end(ap); va_end(ap);
bcli->pid = pipecmdarr(&bcli->fd, NULL, &bcli->fd, bcli->args); list_add_tail(&dstate->bitcoin_req, &bcli->list);
if (bcli->pid < 0) next_bcli(dstate);
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);
} }
static void process_importaddress(struct bitcoin_cli *bcli) static void process_importaddress(struct bitcoin_cli *bcli)

3
daemon/lightningd.c

@ -127,7 +127,8 @@ static struct lightningd_state *lightningd_state(void)
dstate->secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY dstate->secpctx = secp256k1_context_create(SECP256K1_CONTEXT_VERIFY
| SECP256K1_CONTEXT_SIGN); | SECP256K1_CONTEXT_SIGN);
default_config(&dstate->config); default_config(&dstate->config);
dstate->bitcoind_in_progress = 0; list_head_init(&dstate->bitcoin_req);
dstate->bitcoin_req_running = false;
return dstate; return dstate;
} }

7
daemon/lightningd.h

@ -62,11 +62,12 @@ struct lightningd_state {
/* This is us. */ /* This is us. */
struct pubkey id; struct pubkey id;
/* Number of bitcoind commands outstanding. */
unsigned int bitcoind_in_progress;
/* Transactions/txos we are watching. */ /* Transactions/txos we are watching. */
struct txwatch_hash txwatches; struct txwatch_hash txwatches;
struct txowatch_hash txowatches; struct txowatch_hash txowatches;
/* Outstanding bitcoind requests. */
struct list_head bitcoin_req;
bool bitcoin_req_running;
}; };
#endif /* LIGHTNING_DAEMON_LIGHTNING_H */ #endif /* LIGHTNING_DAEMON_LIGHTNING_H */

5
daemon/watch.c

@ -213,10 +213,9 @@ static struct timeout watch_timeout;
static void start_poll_transactions(struct lightningd_state *dstate) 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, log_unusual(dstate->base_log,
"Delaying start poll: %u commands in progress", "Delaying start poll: commands in progress");
dstate->bitcoind_in_progress);
} else } else
bitcoind_poll_transactions(dstate, watched_transaction); bitcoind_poll_transactions(dstate, watched_transaction);
refresh_timeout(dstate, &watch_timeout); refresh_timeout(dstate, &watch_timeout);

Loading…
Cancel
Save