Skip to content

Commit 44d408c

Browse files
committed
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).
1 parent f5999fd commit 44d408c

File tree

1 file changed

+69
-1
lines changed

1 file changed

+69
-1
lines changed

plugins/bcli.c

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -686,8 +686,72 @@ static struct command_result *getutxout(struct command *cmd,
686686
return command_still_pending(cmd);
687687
}
688688

689+
static void bitcoind_failure(struct plugin *p, const char *error_message)
690+
{
691+
const char **cmd = gather_args(bitcoind, "echo", NULL);
692+
const char *err =
693+
tal_fmt(bitcoind, "\n%s\n\n"
694+
"Make sure you have bitcoind running and that bitcoin-cli"
695+
" is able to connect to bitcoind.\n\n"
696+
"You can verify that your Bitcoin Core installation is"
697+
" ready for use by running:\n\n"
698+
" $ %s 'hello world'\n", error_message,
699+
args_string(cmd, cmd));
700+
plugin_err(p, err);
701+
}
702+
703+
static void wait_for_bitcoind(struct plugin *p)
704+
{
705+
int from, status, ret;
706+
pid_t child;
707+
const char **cmd = gather_args(bitcoind, "echo", NULL);
708+
bool printed = false;
709+
710+
for (;;) {
711+
child = pipecmdarr(NULL, &from, &from, cast_const2(char **,cmd));
712+
if (child < 0) {
713+
if (errno == ENOENT)
714+
bitcoind_failure(p, "bitcoin-cli not found. Is bitcoin-cli "
715+
"(part of Bitcoin Core) available in your PATH?");
716+
plugin_err(p, "%s exec failed: %s", cmd[0], strerror(errno));
717+
}
718+
719+
char *output = grab_fd(cmd, from);
720+
721+
while ((ret = waitpid(child, &status, 0)) < 0 && errno == EINTR);
722+
if (ret != child)
723+
bitcoind_failure(p, tal_fmt(bitcoind, "Waiting for %s: %s",
724+
cmd[0], strerror(errno)));
725+
if (!WIFEXITED(status))
726+
bitcoind_failure(p, tal_fmt(bitcoind, "Death of %s: signal %i",
727+
cmd[0], WTERMSIG(status)));
728+
729+
if (WEXITSTATUS(status) == 0)
730+
break;
731+
732+
/* bitcoin/src/rpc/protocol.h:
733+
* RPC_IN_WARMUP = -28, //!< Client still warming up
734+
*/
735+
if (WEXITSTATUS(status) != 28) {
736+
if (WEXITSTATUS(status) == 1)
737+
bitcoind_failure(p, "Could not connect to bitcoind using"
738+
" bitcoin-cli. Is bitcoind running?");
739+
bitcoind_failure(p, tal_fmt(bitcoind, "%s exited with code %i: %s",
740+
cmd[0], WEXITSTATUS(status), output));
741+
}
742+
743+
if (!printed) {
744+
plugin_log(p, LOG_UNUSUAL,
745+
"Waiting for bitcoind to warm up...");
746+
printed = true;
747+
}
748+
sleep(1);
749+
}
750+
tal_free(cmd);
751+
}
752+
689753
/* Initialize the global context when handshake is done. */
690-
static void init(struct plugin *p UNUSED, const char *buffer UNUSED,
754+
static void init(struct plugin *p, const char *buffer UNUSED,
691755
const jsmntok_t *config UNUSED)
692756
{
693757
bitcoind = tal(NULL, struct bitcoind);
@@ -704,6 +768,10 @@ static void init(struct plugin *p UNUSED, const char *buffer UNUSED,
704768
bitcoind->rpcpass = NULL;
705769
bitcoind->rpcconnect = NULL;
706770
bitcoind->rpcport = NULL;
771+
772+
wait_for_bitcoind(p);
773+
plugin_log(p, LOG_INFORM,
774+
"bitcoin-cli initialized and connected to bitcoind.");
707775
}
708776

709777
static const struct plugin_command commands[] = {

0 commit comments

Comments
 (0)