1616import subprocess
1717import time
1818import re
19+ import errno
1920
2021from . import coverage
2122from .authproxy import AuthServiceProxy , JSONRPCException
@@ -130,11 +131,33 @@ def initialize_datadir(dirname, n):
130131 f .write ("listenonion=0\n " )
131132 return datadir
132133
134+ def rpc_url (i , rpchost = None ):
135+ return "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1' , rpc_port (i ))
136+
137+ def wait_for_bitcoind_start (process , url , i ):
138+ '''
139+ Wait for bitcoind to start. This means that RPC is accessible and fully initialized.
140+ Raise an exception if bitcoind exits during initialization.
141+ '''
142+ while True :
143+ if process .poll () is not None :
144+ raise Exception ('bitcoind exited with status %i during initialization' % process .returncode )
145+ try :
146+ rpc = get_rpc_proxy (url , i )
147+ blocks = rpc .getblockcount ()
148+ break # break out of loop on success
149+ except IOError as e :
150+ if e .errno != errno .ECONNREFUSED : # Port not yet open?
151+ raise # unknown IO error
152+ except JSONRPCException as e : # Initialization phase
153+ if e .error ['code' ] != - 28 : # RPC in warmup?
154+ raise # unkown JSON RPC exception
155+ time .sleep (0.25 )
156+
133157def initialize_chain (test_dir ):
134158 """
135159 Create (or copy from cache) a 200-block-long chain and
136160 4 wallets.
137- bitcoind and bitcoin-cli must be in search path.
138161 """
139162
140163 if (not os .path .isdir (os .path .join ("cache" ,"node0" ))
@@ -147,7 +170,6 @@ def initialize_chain(test_dir):
147170 if os .path .isdir (os .path .join ("cache" ,"node" + str (i ))):
148171 shutil .rmtree (os .path .join ("cache" ,"node" + str (i )))
149172
150- devnull = open (os .devnull , "w" )
151173 # Create cache directories, run bitcoinds:
152174 for i in range (4 ):
153175 datadir = initialize_datadir ("cache" , i )
@@ -156,19 +178,15 @@ def initialize_chain(test_dir):
156178 args .append ("-connect=127.0.0.1:" + str (p2p_port (0 )))
157179 bitcoind_processes [i ] = subprocess .Popen (args )
158180 if os .getenv ("PYTHON_DEBUG" , "" ):
159- print "initialize_chain: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
160- subprocess .check_call ([ os .getenv ("BITCOINCLI" , "bitcoin-cli" ), "-datadir=" + datadir ,
161- "-rpcwait" , "getblockcount" ], stdout = devnull )
181+ print "initialize_chain: bitcoind started, waiting for RPC to come up"
182+ wait_for_bitcoind_start (bitcoind_processes [i ], rpc_url (i ), i )
162183 if os .getenv ("PYTHON_DEBUG" , "" ):
163- print "initialize_chain: bitcoin-cli -rpcwait getblockcount completed"
164- devnull .close ()
184+ print "initialize_chain: RPC succesfully started"
165185
166186 rpcs = []
167-
168187 for i in range (4 ):
169188 try :
170- url = "http://rt:[email protected] :%d" % (
rpc_port (
i ),)
171- rpcs .append (get_rpc_proxy (url , i ))
189+ rpcs .append (get_rpc_proxy (rpc_url (i ), i ))
172190 except :
173191 sys .stderr .write ("Error connecting to " + url + "\n " )
174192 sys .exit (1 )
@@ -243,17 +261,12 @@ def start_node(i, dirname, extra_args=None, rpchost=None, timewait=None, binary=
243261 args = [ binary , "-datadir=" + datadir , "-server" , "-keypool=1" , "-discover=0" , "-rest" , "-mocktime=" + str (get_mocktime ()) ]
244262 if extra_args is not None : args .extend (extra_args )
245263 bitcoind_processes [i ] = subprocess .Popen (args )
246- devnull = open (os .devnull , "w" )
247264 if os .getenv ("PYTHON_DEBUG" , "" ):
248- print "start_node: bitcoind started, calling bitcoin-cli -rpcwait getblockcount"
249- subprocess .check_call ([ os .getenv ("BITCOINCLI" , "bitcoin-cli" ), "-datadir=" + datadir ] +
250- _rpchost_to_args (rpchost ) +
251- ["-rpcwait" , "getblockcount" ], stdout = devnull )
265+ print "start_node: bitcoind started, waiting for RPC to come up"
266+ url = rpc_url (i , rpchost )
267+ wait_for_bitcoind_start (bitcoind_processes [i ], url , i )
252268 if os .getenv ("PYTHON_DEBUG" , "" ):
253- print "start_node: calling bitcoin-cli -rpcwait getblockcount returned"
254- devnull .close ()
255- url = "http://rt:rt@%s:%d" % (rpchost or '127.0.0.1' , rpc_port (i ))
256-
269+ print "start_node: RPC succesfully started"
257270 proxy = get_rpc_proxy (url , i , timeout = timewait )
258271
259272 if COVERAGE_DIR :
@@ -267,7 +280,14 @@ def start_nodes(num_nodes, dirname, extra_args=None, rpchost=None, binary=None):
267280 """
268281 if extra_args is None : extra_args = [ None for i in range (num_nodes ) ]
269282 if binary is None : binary = [ None for i in range (num_nodes ) ]
270- return [ start_node (i , dirname , extra_args [i ], rpchost , binary = binary [i ]) for i in range (num_nodes ) ]
283+ rpcs = []
284+ try :
285+ for i in range (num_nodes ):
286+ rpcs .append (start_node (i , dirname , extra_args [i ], rpchost , binary = binary [i ]))
287+ except : # If one node failed to start, stop the others
288+ stop_nodes (rpcs )
289+ raise
290+ return rpcs
271291
272292def log_filename (dirname , n_node , logname ):
273293 return os .path .join (dirname , "node" + str (n_node ), "regtest" , logname )
0 commit comments