1
0

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:
SomberNight
2025-06-30 22:36:49 +00:00
parent 5cb844fc7c
commit 61623d6d56

View File

@@ -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: