run_electrum: have daemon manage Plugins object, and call Plugins.stop
Plugins.stop was never called, so the Plugins thread only stopped
because of the is_running() check in run(), which triggers too late:
the Plugins thread was stopping after the main thread stopped.
E.g. playing around in the qt wizard with wallet creation for a Trezor,
and closing the wizard (only window):
``` 24.85 | E | p/plugin.Plugins |
Traceback (most recent call last):
File "/home/user/wspace/electrum/electrum/util.py", line 386, in run_jobs
job.run()
File "/home/user/wspace/electrum/electrum/plugin.py", line 430, in run
client.timeout(cutoff)
File "/home/user/wspace/electrum/electrum/plugin.py", line 363, in wrapper
return run_in_hwd_thread(partial(func, *args, **kwargs))
File "/home/user/wspace/electrum/electrum/plugin.py", line 355, in run_in_hwd_thread
fut = _hwd_comms_executor.submit(func)
File "/usr/lib/python3.10/concurrent/futures/thread.py", line 167, in submit
raise RuntimeError('cannot schedule new futures after shutdown')
RuntimeError: cannot schedule new futures after shutdown
```
This commit is contained in:
@@ -411,6 +411,7 @@ class Daemon(Logger):
|
||||
if 'wallet_path' in config.cmdline_options:
|
||||
self.logger.warning("Ignoring parameter 'wallet_path' for daemon. "
|
||||
"Use the load_wallet command instead.")
|
||||
self._plugins = None # type: Optional[Plugins]
|
||||
self.asyncio_loop = util.get_asyncio_loop()
|
||||
if not self.config.NETWORK_OFFLINE:
|
||||
self.network = Network(config, daemon=self)
|
||||
@@ -560,6 +561,9 @@ class Daemon(Logger):
|
||||
return True
|
||||
|
||||
def run_daemon(self):
|
||||
# init plugins
|
||||
self._plugins = Plugins(self.config, 'cmdline')
|
||||
# block until we are stopping
|
||||
try:
|
||||
self._stopping_soon_or_errored.wait()
|
||||
except KeyboardInterrupt:
|
||||
@@ -590,6 +594,11 @@ class Daemon(Logger):
|
||||
if self.network:
|
||||
await group.spawn(self.network.stop(full_shutdown=True))
|
||||
await group.spawn(self.taskgroup.cancel_remaining())
|
||||
if self._plugins:
|
||||
self.logger.info("stopping plugins")
|
||||
self._plugins.stop()
|
||||
async with ignore_after(1):
|
||||
await self._plugins.stopped_event_async.wait()
|
||||
finally:
|
||||
if self.listen_jsonrpc:
|
||||
self.logger.info("removing lockfile")
|
||||
@@ -597,18 +606,21 @@ class Daemon(Logger):
|
||||
self.logger.info("stopped")
|
||||
self._stopped_event.set()
|
||||
|
||||
def run_gui(self, config: 'SimpleConfig', plugins: 'Plugins'):
|
||||
def run_gui(self) -> None:
|
||||
assert self.config
|
||||
assert self._plugins
|
||||
threading.current_thread().name = 'GUI'
|
||||
gui_name = config.GUI_NAME
|
||||
gui_name = self.config.GUI_NAME
|
||||
if gui_name in ['lite', 'classic']:
|
||||
gui_name = 'qt'
|
||||
self._plugins = Plugins(self.config, gui_name) # init plugins
|
||||
self.logger.info(f'launching GUI: {gui_name}')
|
||||
try:
|
||||
try:
|
||||
gui = __import__('electrum.gui.' + gui_name, fromlist=['electrum'])
|
||||
except GuiImportError as e:
|
||||
sys.exit(str(e))
|
||||
self.gui_object = gui.ElectrumGui(config=config, daemon=self, plugins=plugins)
|
||||
self.gui_object = gui.ElectrumGui(config=self.config, daemon=self, plugins=self._plugins)
|
||||
if not self._stop_entered:
|
||||
self.gui_object.main()
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user