Exit gracefully in more cases

This commit is contained in:
AuroraWright
2025-10-20 08:02:45 +02:00
parent 042100e989
commit 7721621a2e

View File

@@ -271,8 +271,7 @@ class WebsocketServerThread(threading.Thread):
async with start_server: async with start_server:
await stop_event.wait() await stop_event.wait()
except OSError: except OSError:
logger.error(f"Couldn't start websocket server. Make sure port {websocket_port} is not already in use") exit_with_error(f"Couldn't start websocket server. Make sure port {websocket_port} is not already in use")
terminate_handler()
asyncio.run(main()) asyncio.run(main())
@@ -853,8 +852,7 @@ class ScreenshotThread(threading.Thread):
elif screen_capture_area.startswith('screen_'): elif screen_capture_area.startswith('screen_'):
parts = screen_capture_area.split('_') parts = screen_capture_area.split('_')
if len(parts) != 2 or not parts[1].isdigit(): if len(parts) != 2 or not parts[1].isdigit():
logger.error('Invalid screen_capture_area') exit_with_error('Invalid screen_capture_area')
sys.exit(1)
screen_capture_monitor = int(parts[1]) screen_capture_monitor = int(parts[1])
self.screencapture_mode = 1 self.screencapture_mode = 1
elif len(screen_capture_area.split(',')) == 4: elif len(screen_capture_area.split(',')) == 4:
@@ -871,8 +869,7 @@ class ScreenshotThread(threading.Thread):
if self.screencapture_mode == 1: if self.screencapture_mode == 1:
mon = self.sct.monitors mon = self.sct.monitors
if len(mon) <= screen_capture_monitor: if len(mon) <= screen_capture_monitor:
logger.error('Invalid monitor number in screen_capture_area') exit_with_error('Invalid monitor number in screen_capture_area')
sys.exit(1)
coord_left = mon[screen_capture_monitor]['left'] coord_left = mon[screen_capture_monitor]['left']
coord_top = mon[screen_capture_monitor]['top'] coord_top = mon[screen_capture_monitor]['top']
coord_width = mon[screen_capture_monitor]['width'] coord_width = mon[screen_capture_monitor]['width']
@@ -917,8 +914,7 @@ class ScreenshotThread(threading.Thread):
break break
if not window_index: if not window_index:
logger.error('"screen_capture_area" must be empty, "screen_N" where N is a screen number starting from 1, a valid set of coordinates, or a valid window name') exit_with_error('"screen_capture_area" must be empty, "screen_N" where N is a screen number starting from 1, a valid set of coordinates, or a valid window name')
sys.exit(1)
self.window_id = window_ids[window_index] self.window_id = window_ids[window_index]
window_title = window_titles[window_index] window_title = window_titles[window_index]
@@ -931,8 +927,7 @@ class ScreenshotThread(threading.Thread):
self.window_handle, window_title = self.get_windows_window_handle(screen_capture_area) self.window_handle, window_title = self.get_windows_window_handle(screen_capture_area)
if not self.window_handle: if not self.window_handle:
logger.error('"screen_capture_area" must be empty, "screen_N" where N is a screen number starting from 1, a valid set of coordinates, or a valid window name') exit_with_error('"screen_capture_area" must be empty, "screen_N" where N is a screen number starting from 1, a valid set of coordinates, or a valid window name')
sys.exit(1)
ctypes.windll.shcore.SetProcessDpiAwareness(2) ctypes.windll.shcore.SetProcessDpiAwareness(2)
self.window_visible = not win32gui.IsIconic(self.window_handle) self.window_visible = not win32gui.IsIconic(self.window_handle)
@@ -944,8 +939,7 @@ class ScreenshotThread(threading.Thread):
self.windows_window_tracker_instance.start() self.windows_window_tracker_instance.start()
logger.info(f'Selected window: {window_title}') logger.info(f'Selected window: {window_title}')
else: else:
logger.error('Window capture is only currently supported on Windows and macOS') exit_with_error('Window capture is only currently supported on Windows and macOS')
sys.exit(1)
screen_capture_window_area = config.get_general('screen_capture_window_area') screen_capture_window_area = config.get_general('screen_capture_window_area')
if screen_capture_window_area != 'window': if screen_capture_window_area != 'window':
@@ -956,8 +950,7 @@ class ScreenshotThread(threading.Thread):
elif screen_capture_window_area == '': elif screen_capture_window_area == '':
self.launch_coordinate_picker(False, False) self.launch_coordinate_picker(False, False)
else: else:
logger.error('"screen_capture_window_area" must be empty, "window" for the whole window, or a valid set of coordinates') exit_with_error('"screen_capture_window_area" must be empty, "window" for the whole window, or a valid set of coordinates')
sys.exit(1)
def get_windows_window_handle(self, window_title): def get_windows_window_handle(self, window_title):
def callback(hwnd, window_title_part): def callback(hwnd, window_title_part):
@@ -1204,8 +1197,7 @@ class ScreenshotThread(threading.Thread):
screen_selection = get_screen_selection(None, self.coordinate_selector_combo_enabled) screen_selection = get_screen_selection(None, self.coordinate_selector_combo_enabled)
if not screen_selection: if not screen_selection:
if on_init: if on_init:
logger.error('Picker window was closed or an error occurred') exit_with_error('Picker window was closed or an error occurred')
sys.exit(1)
else: else:
logger.warning('Picker window was closed or an error occurred, leaving settings unchanged') logger.warning('Picker window was closed or an error occurred, leaving settings unchanged')
return return
@@ -1544,6 +1536,12 @@ def terminate_handler(sig=None, frame=None):
terminated.set() terminated.set()
def exit_with_error(error):
logger.error(error)
terminate_handler()
sys.exit(1)
def user_input_thread_run(): def user_input_thread_run():
if sys.platform == 'win32': if sys.platform == 'win32':
import msvcrt import msvcrt
@@ -1657,8 +1655,7 @@ def run():
engine_secondary = engine_class.key engine_secondary = engine_class.key
if len(engine_keys) == 0: if len(engine_keys) == 0:
logger.error('No engines available!') exit_with_error('No engines available!')
sys.exit(1)
if default_engine_setting and not default_engine: if default_engine_setting and not default_engine:
logger.warning("Couldn't find selected engine, using the first one in the list") logger.warning("Couldn't find selected engine, using the first one in the list")
@@ -1732,9 +1729,7 @@ def run():
periodic_screenshot_queue = queue.Queue() periodic_screenshot_queue = queue.Queue()
screen_capture_periodic = True screen_capture_periodic = True
if not (screen_capture_on_combo or screen_capture_periodic): if not (screen_capture_on_combo or screen_capture_periodic):
logger.error('screen_capture_delay_secs or screen_capture_combo need to be valid values') exit_with_error('screen_capture_delay_secs or screen_capture_combo need to be valid values')
terminate_handler()
sys.exit(1)
screenshot_request_queue = queue.Queue() screenshot_request_queue = queue.Queue()
screenshot_thread = ScreenshotThread() screenshot_thread = ScreenshotThread()
screenshot_thread.start() screenshot_thread.start()
@@ -1743,18 +1738,14 @@ def run():
read_from_readable.append('websocket') read_from_readable.append('websocket')
if 'unixsocket' in (read_from, read_from_secondary): if 'unixsocket' in (read_from, read_from_secondary):
if sys.platform == 'win32': if sys.platform == 'win32':
logger.error('"unixsocket" is not currently supported on Windows') exit_with_error('"unixsocket" is not currently supported on Windows')
terminate_handler()
sys.exit(1)
socket_path = Path('/tmp/owocr.sock') socket_path = Path('/tmp/owocr.sock')
if socket_path.exists(): if socket_path.exists():
try: try:
test_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) test_socket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
test_socket.connect(str(socket_path)) test_socket.connect(str(socket_path))
test_socket.close() test_socket.close()
logger.error('Unix domain socket is already in use') exit_with_error('Unix domain socket is already in use')
terminate_handler()
sys.exit(1)
except ConnectionRefusedError: except ConnectionRefusedError:
socket_path.unlink() socket_path.unlink()
unix_socket_server = socketserver.ThreadingUnixStreamServer(str(socket_path), UnixSocketRequestHandler) unix_socket_server = socketserver.ThreadingUnixStreamServer(str(socket_path), UnixSocketRequestHandler)
@@ -1767,15 +1758,11 @@ def run():
read_from_readable.append('clipboard') read_from_readable.append('clipboard')
if any(i and i not in non_path_inputs for i in (read_from, read_from_secondary)): if any(i and i not in non_path_inputs for i in (read_from, read_from_secondary)):
if all(i and i not in non_path_inputs for i in (read_from, read_from_secondary)): if all(i and i not in non_path_inputs for i in (read_from, read_from_secondary)):
logger.error("read_from and read_from_secondary can't both be directory paths") exit_with_error("read_from and read_from_secondary can't both be directory paths")
terminate_handler()
sys.exit(1)
delete_images = config.get_general('delete_images') delete_images = config.get_general('delete_images')
read_from_path = Path(read_from) if read_from not in non_path_inputs else Path(read_from_secondary) read_from_path = Path(read_from) if read_from not in non_path_inputs else Path(read_from_secondary)
if not read_from_path.is_dir(): if not read_from_path.is_dir():
logger.error('read_from and read_from_secondary must be either "websocket", "unixsocket", "clipboard", "screencapture", or a path to a directory') exit_with_error('read_from and read_from_secondary must be either "websocket", "unixsocket", "clipboard", "screencapture", or a path to a directory')
terminate_handler()
sys.exit(1)
directory_watcher_thread = DirectoryWatcher(read_from_path) directory_watcher_thread = DirectoryWatcher(read_from_path)
directory_watcher_thread.start() directory_watcher_thread.start()
read_from_readable.append(f'directory {read_from_path}') read_from_readable.append(f'directory {read_from_path}')
@@ -1790,9 +1777,7 @@ def run():
write_to_readable = write_to write_to_readable = write_to
else: else:
if Path(write_to).suffix.lower() != '.txt': if Path(write_to).suffix.lower() != '.txt':
logger.error('write_to must be either "websocket", "clipboard" or a path to a text file') exit_with_error('write_to must be either "websocket", "clipboard" or a path to a text file')
terminate_handler()
sys.exit(1)
write_to_readable = f'file {write_to}' write_to_readable = f'file {write_to}'
process_queue = (any(i in ('clipboard', 'websocket', 'unixsocket') for i in (read_from, read_from_secondary)) or read_from_path or screen_capture_on_combo) process_queue = (any(i in ('clipboard', 'websocket', 'unixsocket') for i in (read_from, read_from_secondary)) or read_from_path or screen_capture_on_combo)