plugins/bcli: wait for bitcoind to be warmed up at init

This is also taken and adapted from lightningd/bitcoind.

The call to 'getblockchaininfo' is replaced by 'echo' as we don't
make use of the result and the former can sometimes be slow (e.g. on
IBD).
This commit is contained in:
darosior 2020-01-04 20:56:58 +01:00 committed by Rusty Russell
parent 70a79e3998
commit f81cc9f552

View file

@ -686,8 +686,72 @@ static struct command_result *getutxout(struct command *cmd,
return command_still_pending(cmd); return command_still_pending(cmd);
} }
static void bitcoind_failure(struct plugin *p, const char *error_message)
{
const char **cmd = gather_args(bitcoind, "echo", NULL);
const char *err =
tal_fmt(bitcoind, "\n%s\n\n"
"Make sure you have bitcoind running and that bitcoin-cli"
" is able to connect to bitcoind.\n\n"
"You can verify that your Bitcoin Core installation is"
" ready for use by running:\n\n"
" $ %s 'hello world'\n", error_message,
args_string(cmd, cmd));
plugin_err(p, err);
}
static void wait_for_bitcoind(struct plugin *p)
{
int from, status, ret;
pid_t child;
const char **cmd = gather_args(bitcoind, "echo", NULL);
bool printed = false;
for (;;) {
child = pipecmdarr(NULL, &from, &from, cast_const2(char **,cmd));
if (child < 0) {
if (errno == ENOENT)
bitcoind_failure(p, "bitcoin-cli not found. Is bitcoin-cli "
"(part of Bitcoin Core) available in your PATH?");
plugin_err(p, "%s exec failed: %s", cmd[0], strerror(errno));
}
char *output = grab_fd(cmd, from);
while ((ret = waitpid(child, &status, 0)) < 0 && errno == EINTR);
if (ret != child)
bitcoind_failure(p, tal_fmt(bitcoind, "Waiting for %s: %s",
cmd[0], strerror(errno)));
if (!WIFEXITED(status))
bitcoind_failure(p, tal_fmt(bitcoind, "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) {
if (WEXITSTATUS(status) == 1)
bitcoind_failure(p, "Could not connect to bitcoind using"
" bitcoin-cli. Is bitcoind running?");
bitcoind_failure(p, tal_fmt(bitcoind, "%s exited with code %i: %s",
cmd[0], WEXITSTATUS(status), output));
}
if (!printed) {
plugin_log(p, LOG_UNUSUAL,
"Waiting for bitcoind to warm up...");
printed = true;
}
sleep(1);
}
tal_free(cmd);
}
/* Initialize the global context when handshake is done. */ /* Initialize the global context when handshake is done. */
static void init(struct plugin *p UNUSED, const char *buffer UNUSED, static void init(struct plugin *p, const char *buffer UNUSED,
const jsmntok_t *config UNUSED) const jsmntok_t *config UNUSED)
{ {
bitcoind = tal(NULL, struct bitcoind); bitcoind = tal(NULL, struct bitcoind);
@ -704,6 +768,10 @@ static void init(struct plugin *p UNUSED, const char *buffer UNUSED,
bitcoind->rpcpass = NULL; bitcoind->rpcpass = NULL;
bitcoind->rpcconnect = NULL; bitcoind->rpcconnect = NULL;
bitcoind->rpcport = NULL; bitcoind->rpcport = NULL;
wait_for_bitcoind(p);
plugin_log(p, LOG_INFORM,
"bitcoin-cli initialized and connected to bitcoind.");
} }
static const struct plugin_command commands[] = { static const struct plugin_command commands[] = {