URI: 
       tMerge pull request #6634 from SomberNight/202010_fix_main_script_hanging - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit c31ae86bb857c27aea3ab615b649dd17b392179e
   DIR parent ea22d0073ea5f61d53449a7afd072c3fd78003e8
  HTML Author: ThomasV <thomasv@electrum.org>
       Date:   Wed, 28 Oct 2020 16:22:39 +0100
       
       Merge pull request #6634 from SomberNight/202010_fix_main_script_hanging
       
       fix main script hanging (not exiting after exception) in some cases
       Diffstat:
         M run_electrum                        |      40 +++++++++++++++++++++++++------
       
       1 file changed, 33 insertions(+), 7 deletions(-)
       ---
   DIR diff --git a/run_electrum b/run_electrum
       t@@ -37,7 +37,7 @@ if sys.version_info[:3] < _min_python_version_tuple:
        
        import warnings
        import asyncio
       -from typing import TYPE_CHECKING
       +from typing import TYPE_CHECKING, Optional
        
        
        script_dir = os.path.dirname(os.path.realpath(__file__))
       t@@ -95,6 +95,8 @@ from electrum import keystore
        from electrum.util import create_and_start_event_loop
        
        if TYPE_CHECKING:
       +    import threading
       +
            from electrum.plugin import Plugins
        
        _logger = get_logger(__name__)
       t@@ -113,7 +115,7 @@ def prompt_password(prompt, confirm=True):
            return password
        
        
       -def init_cmdline(config_options, wallet_path, server):
       +def init_cmdline(config_options, wallet_path, server, *, config: 'SimpleConfig'):
            cmdname = config.get('cmd')
            cmd = known_commands[cmdname]
        
       t@@ -259,13 +261,20 @@ def init_plugins(config, gui_name):
            from electrum.plugin import Plugins
            return Plugins(config, gui_name)
        
       +
       +loop = None  # type: Optional[asyncio.AbstractEventLoop]
       +stop_loop = None  # type: Optional[asyncio.Future]
       +loop_thread = None  # type: Optional[threading.Thread]
       +
        def sys_exit(i):
            # stop event loop and exit
       -    loop.call_soon_threadsafe(stop_loop.set_result, 1)
       -    loop_thread.join(timeout=1)
       +    if loop:
       +        loop.call_soon_threadsafe(stop_loop.set_result, 1)
       +        loop_thread.join(timeout=1)
            sys.exit(i)
        
       -if __name__ == '__main__':
       +
       +def main():
            # The hook will only be used in the Qt GUI right now
            util.setup_thread_excepthook()
            # on macOS, delete Process Serial Number arg generated for apps launched in Finder
       t@@ -368,8 +377,21 @@ if __name__ == '__main__':
                    os.dup2(so.fileno(), sys.stdout.fileno())
                    os.dup2(se.fileno(), sys.stderr.fileno())
        
       +    global loop, stop_loop, loop_thread
            loop, stop_loop, loop_thread = create_and_start_event_loop()
        
       +    try:
       +        handle_cmd(
       +            cmdname=cmdname,
       +            config=config,
       +            config_options=config_options,
       +        )
       +    except Exception:
       +        _logger.exception("")
       +        sys_exit(1)
       +
       +
       +def handle_cmd(*, cmdname: str, config: 'SimpleConfig', config_options: dict):
            if cmdname == 'gui':
                configure_logging(config)
                fd = daemon.get_file_descriptor(config)
       t@@ -404,7 +426,7 @@ if __name__ == '__main__':
                cmd = known_commands[cmdname]
                wallet_path = config.get_wallet_path()
                if not config.get('offline'):
       -            init_cmdline(config_options, wallet_path, True)
       +            init_cmdline(config_options, wallet_path, True, config=config)
                    timeout = config.get('timeout', 60)
                    if timeout: timeout = int(timeout)
                    try:
       t@@ -421,7 +443,7 @@ if __name__ == '__main__':
                    if cmd.requires_network:
                        print_msg("This command cannot be run offline")
                        sys_exit(1)
       -            init_cmdline(config_options, wallet_path, False)
       +            init_cmdline(config_options, wallet_path, False, config=config)
                    plugins = init_plugins(config, 'cmdline')
                    coro = run_offline_command(config, config_options, plugins)
                    fut = asyncio.run_coroutine_threadsafe(coro, loop)
       t@@ -438,3 +460,7 @@ if __name__ == '__main__':
            elif result is not None:
                print_msg(json_encode(result))
            sys_exit(0)
       +
       +
       +if __name__ == '__main__':
       +    main()