Workaround for SSIPClient using non-daemonic thread and therefore hanging interpreter shutdown

This commit is contained in:
Kovid Goyal 2020-11-17 18:06:36 +05:30
parent 1cacc7484a
commit 85bf7f823e
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 37 additions and 25 deletions

View File

@ -9,5 +9,5 @@ if iswindows:
elif ismacos: elif ismacos:
pass pass
else: else:
from .linux import speak_simple_text from .linux import Client
speak_simple_text Client

View File

@ -2,29 +2,30 @@
# vim:fileencoding=utf-8 # vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net> # License: GPL v3 Copyright: 2020, Kovid Goyal <kovid at kovidgoyal.net>
import atexit
from .errors import TTSSystemUnavailable from .errors import TTSSystemUnavailable
def get_client(): class Client:
client = getattr(get_client, 'ans', None)
if client is not None:
return client
from speechd.client import SSIPClient, SpawnError
try:
client = get_client.ans = SSIPClient('calibre')
except SpawnError as err:
raise TTSSystemUnavailable(_('Could not find speech-dispatcher on your system. Please install it.'), str(err))
atexit.register(client.close)
return client
def __init__(self):
self.create_ssip_client()
def speak_simple_text(text): def create_ssip_client(self):
client = get_client() from speechd.client import SSIPClient, SpawnError
from speechd.client import SSIPCommunicationError try:
try: self.ssip_client = SSIPClient('calibre')
client.speak(text) except SpawnError as err:
except SSIPCommunicationError: raise TTSSystemUnavailable(_('Could not find speech-dispatcher on your system. Please install it.'), str(err))
get_client.ans = None
client = get_client() def __del__(self):
client.speak(text) self.ssip_client.close()
del self.ssip_client
def speak_simple_text(self, text):
from speechd.client import SSIPCommunicationError
try:
self.ssip_client.speak(text)
except SSIPCommunicationError:
self.ssip_client.close()
self.create_ssip_client()
self.ssip_client.speak(text)

View File

@ -674,6 +674,7 @@ class EbookViewer(MainWindow):
return return
self.shutting_down = True self.shutting_down = True
self.search_widget.shutdown() self.search_widget.shutdown()
self.web_view.shutdown()
try: try:
self.save_state() self.save_state()
self.save_annotations() self.save_annotations()

View File

@ -467,6 +467,7 @@ class WebView(RestartingWebEngineView):
def __init__(self, parent=None): def __init__(self, parent=None):
self._host_widget = None self._host_widget = None
self._tts_client = None
self.callback_id_counter = count() self.callback_id_counter = count()
self.callback_map = {} self.callback_map = {}
self.current_cfi = self.current_content_file = None self.current_cfi = self.current_content_file = None
@ -529,9 +530,18 @@ class WebView(RestartingWebEngineView):
self.inspector = Inspector(parent.inspector_dock.toggleViewAction(), self) self.inspector = Inspector(parent.inspector_dock.toggleViewAction(), self)
parent.inspector_dock.setWidget(self.inspector) parent.inspector_dock.setWidget(self.inspector)
@property
def tts_client(self):
if self._tts_client is None:
from calibre.gui2.tts.implementation import Client
self._tts_client = Client()
return self._tts_client
def speak_simple_text(self, text): def speak_simple_text(self, text):
from calibre.gui2.tts.implementation import speak_simple_text self.tts_client.speak_simple_text(text)
speak_simple_text(text)
def shutdown(self):
self._tts_client = None
def set_shortcut_map(self, smap): def set_shortcut_map(self, smap):
self.shortcut_map = smap self.shortcut_map = smap