Browse Source

qt gui: faster clean-up of hung UpdateCheckThread during exit

If you closed a main_window soon after opening it, and the UpdateCheckThread network request was slow
and still in progress, the gui would freeze until the network request finished.
master
SomberNight 1 year ago
parent
commit
8db2489739
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 3
      electrum/gui/qt/main_window.py
  2. 11
      electrum/gui/qt/update_checker.py

3
electrum/gui/qt/main_window.py

@ -2525,8 +2525,7 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener):
self.close_wallet() self.close_wallet()
if self._update_check_thread: if self._update_check_thread:
self._update_check_thread.exit() self._update_check_thread.stop()
self._update_check_thread.wait()
if self.tray: if self.tray:
self.tray = None self.tray = None
self.gui_object.timer.timeout.disconnect(self.timer_actions) self.gui_object.timer.timeout.disconnect(self.timer_actions)

11
electrum/gui/qt/update_checker.py

@ -4,6 +4,7 @@
import asyncio import asyncio
import base64 import base64
from typing import Optional
from PyQt6.QtCore import Qt, QThread, pyqtSignal from PyQt6.QtCore import Qt, QThread, pyqtSignal
from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QLabel, QProgressBar, from PyQt6.QtWidgets import (QWidget, QVBoxLayout, QLabel, QProgressBar,
@ -102,6 +103,7 @@ class UpdateCheckThread(QThread, Logger):
QThread.__init__(self) QThread.__init__(self)
Logger.__init__(self) Logger.__init__(self)
self.network = Network.get_instance() self.network = Network.get_instance()
self._fut = None # type: Optional[asyncio.Future]
async def get_update_info(self): async def get_update_info(self):
# note: Use long timeout here as it is not critical that we get a response fast, # note: Use long timeout here as it is not critical that we get a response fast,
@ -137,10 +139,17 @@ class UpdateCheckThread(QThread, Logger):
if not self.network: if not self.network:
self.failed.emit() self.failed.emit()
return return
self._fut = asyncio.run_coroutine_threadsafe(self.get_update_info(), self.network.asyncio_loop)
try: try:
update_info = asyncio.run_coroutine_threadsafe(self.get_update_info(), self.network.asyncio_loop).result() update_info = self._fut.result()
except Exception as e: except Exception as e:
self.logger.info(f"got exception: '{repr(e)}'") self.logger.info(f"got exception: '{repr(e)}'")
self.failed.emit() self.failed.emit()
else: else:
self.checked.emit(update_info) self.checked.emit(update_info)
def stop(self):
if self._fut:
self._fut.cancel()
self.exit()
self.wait()

Loading…
Cancel
Save