daemon lockfile: if create_time is in the future, don't wait for it :D
- if Electrum cannot do a graceful shutdown, the daemon lockfile won't get cleaned up
- the daemon lockfile contains the creation time of the daemon
- then, especially for an always offline phone/laptop, if the battery dies, the clock
might go back to the past
- the bug: next time Electrum starts, the program will wait until create_time + 1.0
before giving up on the daemon and creating a new one
closes https://github.com/spesmilo/electrum/issues/9802
- certainly fixes at least https://github.com/spesmilo/electrum/issues/9802#issuecomment-3020220593
- the OP there might or might not be the same issue
closes https://github.com/spesmilo/electrum/issues/9529
- same here, might or might not be the same issue
the logic bug is quite old, from e6020975a5
This commit is contained in:
@@ -111,12 +111,13 @@ def get_file_descriptor(config: SimpleConfig):
|
||||
|
||||
def request(config: SimpleConfig, endpoint, args=(), timeout: Union[float, int] = 60):
|
||||
lockfile = get_lockfile(config)
|
||||
while True:
|
||||
create_time = None
|
||||
for attempt in range(5):
|
||||
create_time = None # type: Optional[float | int]
|
||||
path = None
|
||||
try:
|
||||
with open(lockfile) as f:
|
||||
socktype, address, create_time = ast.literal_eval(f.read())
|
||||
int(create_time) # raise if not numeric
|
||||
if socktype == 'unix':
|
||||
path = address
|
||||
(host, port) = "127.0.0.1", 0
|
||||
@@ -150,10 +151,17 @@ def request(config: SimpleConfig, endpoint, args=(), timeout: Union[float, int]
|
||||
return fut.result(timeout=timeout)
|
||||
except aiohttp.client_exceptions.ClientConnectorError as e:
|
||||
_logger.info(f"failed to connect to JSON-RPC server {e}")
|
||||
if not create_time or create_time < time.time() - 1.0:
|
||||
# We cannot communicate with the daemon.
|
||||
# If daemon's creation time is very recent, it might still be starting up.
|
||||
# In any other case, we raise: - too old create_time means daemon is likely dead,
|
||||
# - create_time in future means our clock cannot be trusted.
|
||||
if not (create_time <= time.time() <= create_time + 1.0):
|
||||
raise DaemonNotRunning()
|
||||
# Sleep a bit and try again; it might have just been started
|
||||
# Sleep a bit and try again; daemon might have just been started
|
||||
time.sleep(1.0)
|
||||
# how did we even get here?! the clock must be going haywire.
|
||||
_logger.error(f"Failed to connect to JSON-RPC server. Exhausted all attempts.")
|
||||
raise DaemonNotRunning()
|
||||
|
||||
|
||||
def wait_until_daemon_becomes_ready(*, config: SimpleConfig, timeout=5) -> bool:
|
||||
|
||||
Reference in New Issue
Block a user