From 4439838ee7d115e9a3f7eda212fb053649b44319 Mon Sep 17 00:00:00 2001 From: Miguel Jacq Date: Wed, 31 May 2023 15:38:52 +1000 Subject: Raise a Waitress exception into the UI with a modal dialog and reset the share if it occurs --- cli/onionshare_cli/web/web.py | 26 +++++++++++++++++--------- desktop/onionshare/gui_common.py | 9 ++++++++- desktop/onionshare/resources/locale/en.json | 3 ++- desktop/onionshare/tab/mode/__init__.py | 4 +++- desktop/onionshare/threads.py | 14 ++++++++++---- 5 files changed, 40 insertions(+), 16 deletions(-) diff --git a/cli/onionshare_cli/web/web.py b/cli/onionshare_cli/web/web.py index 7da05509..a6ccbeb0 100644 --- a/cli/onionshare_cli/web/web.py +++ b/cli/onionshare_cli/web/web.py @@ -57,6 +57,12 @@ except Exception: pass +class WaitressException(Exception): + """ + There was a problem starting the waitress web server. + """ + + class Web: """ The Web object is the OnionShare web server, powered by flask @@ -349,14 +355,17 @@ class Web: if self.mode == "chat": self.socketio.run(self.app, host=host, port=port) else: - self.waitress = create_server( - self.app, - host=host, - port=port, - clear_untrusted_proxy_headers=True, - ident="OnionShare", - ) - self.waitress.run() + try: + self.waitress = create_server( + self.app, + host=host, + port=port, + clear_untrusted_proxy_headers=True, + ident="OnionShare", + ) + self.waitress.run() + except Exception as e: + raise WaitressException(f"Error starting Waitress: {e}") def stop(self, port): """ @@ -389,7 +398,6 @@ class Web: def waitress_custom_shutdown(self): """Shutdown the Waitress server immediately""" # Code borrowed from https://github.com/Pylons/webtest/blob/4b8a3ebf984185ff4fefb31b4d0cf82682e1fcf7/webtest/http.py#L93-L104 - self.waitress.was_shutdown = True while self.waitress._map: triggers = list(self.waitress._map.values()) for trigger in triggers: diff --git a/desktop/onionshare/gui_common.py b/desktop/onionshare/gui_common.py index bb7e1f1b..e3d712f5 100644 --- a/desktop/onionshare/gui_common.py +++ b/desktop/onionshare/gui_common.py @@ -41,7 +41,7 @@ from onionshare_cli.onion import ( PortNotAvailable, ) from onionshare_cli.meek import Meek - +from onionshare_cli.web.web import WaitressException class GuiCommon: """ @@ -581,6 +581,13 @@ class GuiCommon: return strings._("error_port_not_available") return None + @staticmethod + def get_translated_web_error(e): + """ + Takes an exception defined in web.py and returns a translated error message + """ + if type(e) is WaitressException: + return strings._("waitress_web_server_error") class ToggleCheckbox(QtWidgets.QCheckBox): def __init__(self, text): diff --git a/desktop/onionshare/resources/locale/en.json b/desktop/onionshare/resources/locale/en.json index 5dfb831e..c9e6d86a 100644 --- a/desktop/onionshare/resources/locale/en.json +++ b/desktop/onionshare/resources/locale/en.json @@ -252,5 +252,6 @@ "moat_bridgedb_error": "Could not contact BridgeDB.", "moat_captcha_error": "Incorrect solution. Please try again.", "moat_solution_empty_error": "Enter the characters from the image", - "mode_tor_not_connected_label": "OnionShare is not connected to the Tor network" + "mode_tor_not_connected_label": "OnionShare is not connected to the Tor network", + "waitress_web_server_error": "There was a problem starting the web server" } diff --git a/desktop/onionshare/tab/mode/__init__.py b/desktop/onionshare/tab/mode/__init__.py index 27958d84..34d78cbd 100644 --- a/desktop/onionshare/tab/mode/__init__.py +++ b/desktop/onionshare/tab/mode/__init__.py @@ -27,7 +27,7 @@ from .mode_settings_widget import ModeSettingsWidget from ..server_status import ServerStatus from ... import strings -from ...threads import OnionThread, AutoStartTimer +from ...threads import OnionThread, WebThread, AutoStartTimer from ...widgets import Alert, MinimumSizeWidget @@ -294,6 +294,8 @@ class Mode(QtWidgets.QWidget): self.onion_thread.success.connect(self.starting_server_step2.emit) self.onion_thread.success_early.connect(self.starting_server_early.emit) self.onion_thread.error.connect(self.starting_server_error.emit) + self.web_thread = WebThread(self) + self.web_thread.error.connect(self.starting_server_error.emit) self.onion_thread.start() def start_scheduled_service(self, obtain_onion_early=False): diff --git a/desktop/onionshare/threads.py b/desktop/onionshare/threads.py index b3d51d49..6eeeb97f 100644 --- a/desktop/onionshare/threads.py +++ b/desktop/onionshare/threads.py @@ -39,6 +39,8 @@ from onionshare_cli.onion import ( PortNotAvailable, ) +from onionshare_cli.web.web import WaitressException + from . import strings @@ -83,7 +85,6 @@ class OnionThread(QtCore.QThread): # wait for modules in thread to load, preventing a thread-related cx_Freeze crash time.sleep(0.2) # start onionshare http service in new thread - self.mode.web_thread = WebThread(self.mode) self.mode.web_thread.start() self.success.emit() @@ -122,9 +123,14 @@ class WebThread(QtCore.QThread): def run(self): self.mode.common.log("WebThread", "run") - self.mode.web.start(self.mode.app.port) - self.success.emit() - + try: + self.mode.web.start(self.mode.app.port) + self.success.emit() + except WaitressException as e: + message = self.mode.common.gui.get_translated_web_error(e) + self.mode.common.log("WebThread", "run", message) + self.error.emit(message) + return class AutoStartTimer(QtCore.QThread): """ -- cgit v1.2.3-54-g00ecf