Merge #7744: test_framework: detect failure of bitcoind startup

018b60c test_framework: detect failure of bitcoind startup (Wladimir J. van der Laan)
This commit is contained in:
Wladimir J. van der Laan 2016-03-29 17:16:21 +02:00
commit d8e862a5a7
No known key found for this signature in database
GPG key ID: 74810B012346C9A6

View file

@ -16,6 +16,7 @@ import shutil
import subprocess import subprocess
import time import time
import re import re
import errno
from . import coverage from . import coverage
from .authproxy import AuthServiceProxy, JSONRPCException from .authproxy import AuthServiceProxy, JSONRPCException
@ -130,11 +131,33 @@ def initialize_datadir(dirname, n):
f.write("listenonion=0\n") f.write("listenonion=0\n")
return datadir return datadir
def rpc_url(i, rpchost=None):
return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
def wait_for_bitcoind_start(process, url, i):
'''
Wait for bitcoind to start. This means that RPC is accessible and fully initialized.
Raise an exception if bitcoind exits during initialization.
'''
while True:
if process.poll() is not None:
raise Exception('bitcoind exited with status %i during initialization' % process.returncode)
try:
rpc = get_rpc_proxy(url, i)
blocks = rpc.getblockcount()
break # break out of loop on success
except IOError as e:
if e.errno != errno.ECONNREFUSED: # Port not yet open?
raise # unknown IO error
except JSONRPCException as e: # Initialization phase
if e.error['code'] != -28: # RPC in warmup?
raise # unkown JSON RPC exception
time.sleep(0.25)
def initialize_chain(test_dir): def initialize_chain(test_dir):
""" """
Create (or copy from cache) a 200-block-long chain and Create (or copy from cache) a 200-block-long chain and
4 wallets. 4 wallets.
bitcoind and bitcoin-cli must be in search path.
""" """
if (not os.path.isdir(os.path.join("cache","node0")) if (not os.path.isdir(os.path.join("cache","node0"))
@ -147,7 +170,6 @@ def initialize_chain(test_dir):
if os.path.isdir(os.path.join("cache","node"+str(i))): if os.path.isdir(os.path.join("cache","node"+str(i))):
shutil.rmtree(os.path.join("cache","node"+str(i))) shutil.rmtree(os.path.join("cache","node"+str(i)))
devnull = open(os.devnull, "w")
# Create cache directories, run bitcoinds: # Create cache directories, run bitcoinds:
for i in range(4): for i in range(4):
datadir=initialize_datadir("cache", i) datadir=initialize_datadir("cache", i)
@ -156,19 +178,15 @@ def initialize_chain(test_dir):
args.append("-connect=127.0.0.1:"+str(p2p_port(0))) args.append("-connect=127.0.0.1:"+str(p2p_port(0)))
bitcoind_processes[i] = subprocess.Popen(args) bitcoind_processes[i] = subprocess.Popen(args)
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" print "initialize_chain: bitcoind started, waiting for RPC to come up"
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir, wait_for_bitcoind_start(bitcoind_processes[i], rpc_url(i), i)
"-rpcwait", "getblockcount"], stdout=devnull)
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed" print "initialize_chain: RPC succesfully started"
devnull.close()
rpcs = [] rpcs = []
for i in range(4): for i in range(4):
try: try:
url = "http://rt:rt@127.0.0.1:%d" % (rpc_port(i),) rpcs.append(get_rpc_proxy(rpc_url(i), i))
rpcs.append(get_rpc_proxy(url, i))
except: except:
sys.stderr.write("Error connecting to "+url+"\n") sys.stderr.write("Error connecting to "+url+"\n")
sys.exit(1) sys.exit(1)
@ -243,17 +261,12 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-mocktime="+str(get_mocktime()) ] args = [ binary, "-datadir="+datadir, "-server", "-keypool=1", "-discover=0", "-rest", "-mocktime="+str(get_mocktime()) ]
if extra_args is not None: args.extend(extra_args) if extra_args is not None: args.extend(extra_args)
bitcoind_processes[i] = subprocess.Popen(args) bitcoind_processes[i] = subprocess.Popen(args)
devnull = open(os.devnull, "w")
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount" print "start_node: bitcoind started, waiting for RPC to come up"
subprocess.check_call([ os.getenv("BITCOINCLI", "bitcoin-cli"), "-datadir="+datadir] + url = rpc_url(i, rpchost)
_rpchost_to_args(rpchost) + wait_for_bitcoind_start(bitcoind_processes[i], url, i)
["-rpcwait", "getblockcount"], stdout=devnull)
if os.getenv("PYTHON_DEBUG", ""): if os.getenv("PYTHON_DEBUG", ""):
print "start_node: calling bitcoin-cli -rpcwait getblockcount returned" print "start_node: RPC succesfully started"
devnull.close()
url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1', rpc_port(i))
proxy = get_rpc_proxy(url, i, timeout=timewait) proxy = get_rpc_proxy(url, i, timeout=timewait)
if COVERAGE_DIR: if COVERAGE_DIR:
@ -267,7 +280,14 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
""" """
if extra_args is None: extra_args = [ None for i in range(num_nodes) ] if extra_args is None: extra_args = [ None for i in range(num_nodes) ]
if binary is None: binary = [ None for i in range(num_nodes) ] if binary is None: binary = [ None for i in range(num_nodes) ]
return [ start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]) for i in range(num_nodes) ] rpcs = []
try:
for i in range(num_nodes):
rpcs.append(start_node(i, dirname, extra_args[i], rpchost, binary=binary[i]))
except: # If one node failed to start, stop the others
stop_nodes(rpcs)
raise
return rpcs
def log_filename(dirname, n_node, logname): def log_filename(dirname, n_node, logname):
return os.path.join(dirname, "node"+str(n_node), "regtest", logname) return os.path.join(dirname, "node"+str(n_node), "regtest", logname)