# Buggy code
def critical_error():
    jlog.error("Failure to get blockheight from Bitcoin Core.")
    self.stopService()
    return False


# Traceback (jmclient.storage.StorageError)
2020-08-20 13:51:53,349 [DEBUG]  >>privmsg on darkscience: nick=JXXX cmd=pubkey msg=8XXX
2020-08-20 13:52:02,337 [DEBUG]  mix depths that have enough = {0: XXX}
2020-08-20 13:52:02,338 [INFO]  filling offer, mixdepth=0, amount=2XXX
2020-08-20 13:52:02,893 [INFO]  sending output to address=3XXX
Unhandled Error
Traceback (most recent call last):
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/protocols/amp.py", line 1041, in _commandReceived
deferred = self.dispatchCommand(box)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/protocols/amp.py", line 1099, in dispatchCommand
return maybeDeferred(responder, box)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/internet/defer.py", line 151, in maybeDeferred
result = f(*args, **kw)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/protocols/amp.py", line 1186, in doit
return maybeDeferred(aCallable, **kw).addCallback(
--- <exception caught here> ---
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/internet/defer.py", line 654, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/protocols/amp.py", line 1169, in checkKnownErrors
key = error.trap(*command.allErrors)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/python/failure.py", line 460, in trap
self.raiseException()
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/python/failure.py", line 488, in raiseException
raise self.value.with_traceback(self.tb)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/internet/defer.py", line 151, in maybeDeferred
result = f(*args, **kw)
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/client_protocol.py", line 242, in on_JM_AUTH_RECEIVED
commitment, revelation, amount, kphex)
File "/home/nv01/joinmarket-clientserver/jmbase/jmbase/support.py", line 280, in func_wrapper
return func(inst, *newargs, **kwargs)
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/maker.py", line 105, in on_auth_received
self.wallet_service.save_wallet()
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/wallet_service.py", line 769, in save_wallet
self.wallet.save()
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/wallet.py", line 1531, in save
super().save()
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/wallet.py", line 1838, in save
super().save()
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/wallet.py", line 385, in save
self._utxos.save()
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/wallet.py", line 182, in save
self.storage.save()
File "/home/nv01/joinmarket-clientserver/jmclient/jmclient/storage.py", line 134, in save
raise StorageError("Read-only storage cannot be saved.")
jmclient.storage.StorageError: Read-only storage cannot be saved.

Amp server or network failure unhandled by client application.  Dropping connection!  To avoid, add errbacks to ALL remote commands!
Traceback (most recent call last):
--- <exception caught here> ---
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/internet/defer.py", line 654, in _runCallbacks
current.result = callback(current.result, *args, **kw)
File "/home/nv01/joinmarket-clientserver/jmdaemon/jmdaemon/daemon_protocol.py", line 114, in defaultErrback
ConnectionDone, ConnectionLost)
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/python/failure.py", line 460, in trap
self.raiseException()
File "/home/nv01/joinmarket-clientserver/jmvenv/lib/python3.7/site-packages/twisted/python/failure.py", line 488, in raiseException
raise self.value.with_traceback(self.tb)
twisted.protocols.amp.UnknownRemoteError: Code<UNKNOWN>: Unknown Error

2020-08-20 13:52:45,357 [DEBUG]  Found a new channel, setting to: JXXX,('nXXX.onion', 6667)
2020-08-20 13:52:45,434 [DEBUG]  Nick: JXXX has left.
2020-08-20 13:53:43,052 [DEBUG]  Dynamic switch nick: JXXX
2020-08-20 13:55:25,035 [DEBUG]  JXXX has dusty minsize, capping at 2730
2020-08-20 13:55:25,155 [DEBUG]  JXXX has dusty minsize, capping at 2730
(...)

# Fixed code
def critical_error():
    jlog.error("Critical error updating blockheight.")
    # this cleanup (a) closes the wallet, removing the lock
    # and (b) signals to clients that the service is no longer
    # in a running state, both of which can be useful
    # post reactor shutdown.
    self.stopService()
    stop_reactor()
    return False