Browse Source

daemon: rework stopping

The CLI stop() command can now also stop the GUI.
patch-4
SomberNight 3 years ago
parent
commit
3643b9f056
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 1
      electrum/commands.py
  2. 54
      electrum/daemon.py
  3. 7
      electrum/gui/qt/__init__.py

1
electrum/commands.py

@ -217,7 +217,6 @@ class Commands:
@command('n')
async def stop(self):
"""Stop daemon"""
# TODO it would be nice if this could stop the GUI too
await self.daemon.stop()
return "Daemon stopped"

54
electrum/daemon.py

@ -487,8 +487,8 @@ class Daemon(Logger):
if self.config.get('use_gossip', False):
self.network.start_gossip()
self.stopping_soon = threading.Event()
self.stopped_event = asyncio.Event()
self._stopping_soon = threading.Event()
self._stopped_event = threading.Event()
self.taskgroup = TaskGroup()
asyncio.run_coroutine_threadsafe(self._run(jobs=daemon_jobs), self.asyncio_loop)
@ -507,7 +507,7 @@ class Daemon(Logger):
self.logger.exception("taskgroup died.")
finally:
self.logger.info("taskgroup stopped.")
self.stopping_soon.set()
await self.stop()
def load_wallet(self, path, password, *, manual_upgrades=True) -> Optional[Abstract_Wallet]:
path = standardize_path(path)
@ -571,41 +571,35 @@ class Daemon(Logger):
def run_daemon(self):
try:
self.stopping_soon.wait()
self._stopping_soon.wait()
except KeyboardInterrupt:
self.stopping_soon.set()
self.on_stop()
asyncio.run_coroutine_threadsafe(self.stop(), self.asyncio_loop).result()
self._stopped_event.wait()
async def stop(self):
self.stopping_soon.set()
await self.stopped_event.wait()
def on_stop(self):
if self._stopping_soon.is_set():
return
self._stopping_soon.set()
self.logger.info("stop() entered. initiating shutdown")
try:
self.logger.info("on_stop() entered. initiating shutdown")
if self.gui_object:
self.gui_object.stop()
async def stop_async():
self.logger.info("stopping all wallets")
self.logger.info("stopping all wallets")
async with TaskGroup() as group:
for k, wallet in self._wallets.items():
await group.spawn(wallet.stop())
self.logger.info("stopping network and taskgroup")
async with ignore_after(2):
async with TaskGroup() as group:
for k, wallet in self._wallets.items():
await group.spawn(wallet.stop())
self.logger.info("stopping network and taskgroup")
async with ignore_after(2):
async with TaskGroup() as group:
if self.network:
await group.spawn(self.network.stop(full_shutdown=True))
await group.spawn(self.taskgroup.cancel_remaining())
fut = asyncio.run_coroutine_threadsafe(stop_async(), self.asyncio_loop)
fut.result()
if self.network:
await group.spawn(self.network.stop(full_shutdown=True))
await group.spawn(self.taskgroup.cancel_remaining())
finally:
if self.listen_jsonrpc:
self.logger.info("removing lockfile")
remove_lockfile(get_lockfile(self.config))
self.logger.info("stopped")
self.asyncio_loop.call_soon_threadsafe(self.stopped_event.set)
self._stopped_event.set()
def run_gui(self, config, plugins):
threading.current_thread().setName('GUI')
@ -616,10 +610,14 @@ class Daemon(Logger):
try:
gui = __import__('electrum.gui.' + gui_name, fromlist=['electrum'])
self.gui_object = gui.ElectrumGui(config, self, plugins)
self.gui_object.main()
if not self._stopping_soon.is_set():
self.gui_object.main()
else:
# If daemon.stop() was called before gui_object got created, stop gui now.
self.gui_object.stop()
except BaseException as e:
self.logger.error(f'GUI raised exception: {repr(e)}. shutting down.')
raise
finally:
# app will exit now
self.on_stop()
asyncio.run_coroutine_threadsafe(self.stop(), self.asyncio_loop).result()

7
electrum/gui/qt/__init__.py

@ -81,6 +81,7 @@ class OpenFileEventFilter(QObject):
class QElectrumApplication(QApplication):
new_window_signal = pyqtSignal(str, object)
quit_signal = pyqtSignal()
class QNetworkUpdatedSignalObject(QObject):
@ -132,6 +133,7 @@ class ElectrumGui(Logger):
self.tray = None
self._init_tray()
self.app.new_window_signal.connect(self.start_new_window)
self.app.quit_signal.connect(self.app.quit, Qt.QueuedConnection)
self.set_dark_theme_if_needed()
run_hook('init_qt', self)
@ -428,5 +430,8 @@ class ElectrumGui(Logger):
# on some platforms the exec_ call may not return, so use _cleanup_before_exit
def stop(self):
"""Stops the GUI.
This method is thread-safe.
"""
self.logger.info('closing GUI')
self.app.quit()
self.app.quit_signal.emit()

Loading…
Cancel
Save