From 1ec0085eff253d8e8b96db307881cb8aab6e9e20 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 25 Jan 2022 11:09:42 +0530 Subject: [PATCH] Windows: Fix error if calibre is launched before the previous instance has fully shutdown --- src/calibre/gui2/main.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/src/calibre/gui2/main.py b/src/calibre/gui2/main.py index 288d36e3ec..d48ca09dff 100644 --- a/src/calibre/gui2/main.py +++ b/src/calibre/gui2/main.py @@ -447,7 +447,11 @@ def run_gui_(opts, args, app, gui_debug=None): singleinstance_name = 'GUI' -def send_message(msg): +class FailedToCommunicate(Exception): + pass + + +def send_message(msg, retry_communicate=False): try: send_message_in_process(msg) except Exception: @@ -455,6 +459,10 @@ def send_message(msg): try: send_message_in_process(msg) except Exception as err: + # can happen because the Qt local server pipe is shutdown before + # the single instance mutex is released + if retry_communicate: + raise FailedToCommunicate('retrying') print(_('Failed to contact running instance of calibre'), file=sys.stderr, flush=True) print(err, file=sys.stderr, flush=True) if Application.instance(): @@ -476,14 +484,14 @@ def shutdown_other(): raise SystemExit(_('Failed to shutdown running calibre instance')) -def communicate(opts, args): +def communicate(opts, args, retry_communicate=False): if opts.shutdown_running_calibre: shutdown_other() else: if len(args) > 1: args[1:] = [os.path.abspath(x) if os.path.exists(x) else x for x in args[1:]] import json - if not send_message(b'launched:'+as_bytes(json.dumps(args))): + if not send_message(b'launched:'+as_bytes(json.dumps(args)), retry_communicate=retry_communicate): raise SystemExit(_('Failed to contact running instance of calibre')) raise SystemExit(0) @@ -533,18 +541,24 @@ def main(args=sys.argv): app, opts, args = init_qt(args) except AbortInit: return 1 - with SingleInstance(singleinstance_name) as si: - if si and opts.shutdown_running_calibre: - return 0 - run_main(app, opts, args, gui_debug, si) + try: + with SingleInstance(singleinstance_name) as si: + if si and opts.shutdown_running_calibre: + return 0 + run_main(app, opts, args, gui_debug, si, retry_communicate=True) + except FailedToCommunicate: + with SingleInstance(singleinstance_name) as si: + if si and opts.shutdown_running_calibre: + return 0 + run_main(app, opts, args, gui_debug, si, retry_communicate=False) if after_quit_actions['restart_after_quit']: restart_after_quit() -def run_main(app, opts, args, gui_debug, si): +def run_main(app, opts, args, gui_debug, si, retry_communicate=False): if si: return run_gui(opts, args, app, gui_debug=gui_debug) - communicate(opts, args) + communicate(opts, args, retry_communicate) return 0