Daemon: use lockfile, attempt repeated starts before failing
This commit is contained in:
parent
fe7fd06017
commit
43fc89e2bb
1 changed files with 49 additions and 27 deletions
|
|
@ -34,6 +34,7 @@ class Daemon(MMGenObject):
|
|||
cfg_file = None
|
||||
new_console_mswin = False
|
||||
ps_pid_mswin = False
|
||||
lockfile = None
|
||||
|
||||
def subclass_init(self): pass
|
||||
|
||||
|
|
@ -111,25 +112,40 @@ class Daemon(MMGenObject):
|
|||
return self.run_cmd(self.cli_cmd(*cmds),silent=silent,check=check)
|
||||
|
||||
def start(self,silent=False):
|
||||
if self.is_ready:
|
||||
if self.state == 'ready':
|
||||
if not silent:
|
||||
m = '{} {} already running with pid {}'
|
||||
msg(m.format(self.net_desc,self.desc,self.pid))
|
||||
return
|
||||
|
||||
self.wait_for_state('stopped')
|
||||
|
||||
os.makedirs(self.datadir,exist_ok=True)
|
||||
if self.cfg_file:
|
||||
open('{}/{}'.format(self.datadir,self.cfg_file),'w').write(self.cfg_file_hdr)
|
||||
|
||||
if self.use_pidfile and os.path.exists(self.pidfile):
|
||||
# Parity just overwrites the data in an existing pidfile without zeroing it first,
|
||||
# leading to interesting consequences.
|
||||
os.unlink(self.pidfile)
|
||||
|
||||
for i in range(20):
|
||||
try: ret = self.do_start(silent=silent)
|
||||
except FileNotFoundError as e:
|
||||
die(e.errno,e.strerror)
|
||||
except: pass
|
||||
else: break
|
||||
time.sleep(1)
|
||||
else:
|
||||
os.makedirs(self.datadir,exist_ok=True)
|
||||
if self.cfg_file:
|
||||
open('{}/{}'.format(self.datadir,self.cfg_file),'w').write(self.cfg_file_hdr)
|
||||
if self.use_pidfile and os.path.exists(self.pidfile):
|
||||
# Parity just overwrites the data in an existing pidfile, leading to
|
||||
# interesting consequences.
|
||||
os.unlink(self.pidfile)
|
||||
ret = self.do_start(silent=silent)
|
||||
if self.wait:
|
||||
self.wait_for_state('ready')
|
||||
return ret
|
||||
die(2,'Unable to start daemon')
|
||||
|
||||
if self.wait:
|
||||
self.wait_for_state('ready')
|
||||
|
||||
return ret
|
||||
|
||||
def stop(self,silent=False):
|
||||
if self.is_ready:
|
||||
if self.state == 'ready':
|
||||
ret = self.do_stop(silent=silent)
|
||||
if self.wait:
|
||||
self.wait_for_state('stopped')
|
||||
|
|
@ -150,10 +166,6 @@ class Daemon(MMGenObject):
|
|||
else:
|
||||
die(2,'Daemon wait timeout for {} {} exceeded'.format(self.daemon_id.upper(),self.network))
|
||||
|
||||
@property
|
||||
def is_ready(self):
|
||||
return self.state == 'ready'
|
||||
|
||||
@classmethod
|
||||
def check_implement(cls):
|
||||
m = 'required method {}() missing in class {}'
|
||||
|
|
@ -231,14 +243,15 @@ class CoinDaemon(Daemon):
|
|||
network_ids = ('btc','btc_tn','btc_rt','bch','bch_tn','bch_rt','ltc','ltc_tn','ltc_rt','xmr','eth','etc')
|
||||
|
||||
cd = namedtuple('daemon_data',
|
||||
['coin','cls_pfx','coind_exec','cli_exec','cfg_file','dfl_rpc','dfl_rpc_tn','dfl_rpc_rt'])
|
||||
daemon_ids = {
|
||||
'btc': cd('Bitcoin', 'Bitcoin', 'bitcoind', 'bitcoin-cli', 'bitcoin.conf', 8332,18332,18444),
|
||||
'bch': cd('Bcash', 'Bitcoin', 'bitcoind-abc','bitcoin-cli', 'bitcoin.conf', 8442,18442,18553),# MMGen RPC dfls
|
||||
'ltc': cd('Litecoin', 'Bitcoin', 'litecoind', 'litecoin-cli','litecoin.conf', 9332,19332,19444),
|
||||
'xmr': cd('Monero', 'Monero', 'monerod', 'monerod', 'bitmonero.conf',18081,None,None),
|
||||
'eth': cd('Ethereum', 'Ethereum','parity', 'parity', 'parity.conf', 8545,None,None),
|
||||
'etc': cd('Ethereum Classic','Ethereum','parity', 'parity', 'parity.conf', 8545,None,None)
|
||||
['coin','cls_pfx','coind_exec','cli_exec','cfg_file','testnet_dir','dfl_rpc','dfl_rpc_tn','dfl_rpc_rt'])
|
||||
|
||||
daemon_ids = { # for BCH we use non-standard RPC ports
|
||||
'btc': cd('Bitcoin', 'Bitcoin', 'bitcoind', 'bitcoin-cli', 'bitcoin.conf', 'testnet3',8332,18332,18444),
|
||||
'bch': cd('Bcash', 'Bitcoin', 'bitcoind-abc','bitcoin-cli', 'bitcoin.conf', 'testnet3',8442,18442,18553),
|
||||
'ltc': cd('Litecoin', 'Bitcoin', 'litecoind', 'litecoin-cli','litecoin.conf','testnet4',9332,19332,19444),
|
||||
'xmr': cd('Monero', 'Monero', 'monerod', 'monerod', 'bitmonero.conf',None, 18081,None,None),
|
||||
'eth': cd('Ethereum', 'Ethereum','parity', 'parity', 'parity.conf', None, 8545, None,None),
|
||||
'etc': cd('Ethereum Classic','Ethereum','parity', 'parity', 'parity.conf', None, 8545, None,None)
|
||||
}
|
||||
|
||||
testnet_arg = []
|
||||
|
|
@ -342,7 +355,7 @@ class BitcoinDaemon(CoinDaemon):
|
|||
if self.platform == 'win' and self.daemon_id == 'bch':
|
||||
self.use_pidfile = False
|
||||
|
||||
if self.network=='testnet':
|
||||
if self.network == 'testnet':
|
||||
self.testnet_arg = ['--testnet']
|
||||
|
||||
self.shared_args = [
|
||||
|
|
@ -366,6 +379,11 @@ class BitcoinDaemon(CoinDaemon):
|
|||
elif self.daemon_id == 'ltc':
|
||||
self.coin_specific_coind_args = ['--mempoolreplacement=1']
|
||||
|
||||
if self.network == 'testnet':
|
||||
self.lockfile = os.path.join(self.datadir,self.testnet_dir,'.cookie')
|
||||
elif self.network == 'mainnet':
|
||||
self.lockfile = os.path.join(self.datadir,'.cookie')
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
cp = self.cli('getblockcount',silent=True,check=False)
|
||||
|
|
@ -373,7 +391,11 @@ class BitcoinDaemon(CoinDaemon):
|
|||
if ("error: couldn't connect" in err
|
||||
or "error: Could not connect" in err
|
||||
or "does not exist" in err ):
|
||||
return 'stopped'
|
||||
# regtest has no cookie file, so test will always fail
|
||||
if self.lockfile and os.path.exists(self.lockfile):
|
||||
return 'busy'
|
||||
else:
|
||||
return 'stopped'
|
||||
elif cp.returncode == 0:
|
||||
return 'ready'
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue