diff --git a/news/fix-procproxy-sys-exit.rst b/news/fix-procproxy-sys-exit.rst new file mode 100644 index 000000000..b1a140816 --- /dev/null +++ b/news/fix-procproxy-sys-exit.rst @@ -0,0 +1,23 @@ +**Added:** + +* + +**Changed:** + +* Now SystemExit that invoked from callable alias follows to exiting from callable alias instead of exiting the entire shell. + +**Deprecated:** + +* + +**Removed:** + +* + +**Fixed:** + +* Built-in commands such as `xonfig -h` and `xontrib -h` no longer cause the shell to exit. + +**Security:** + +* diff --git a/tests/test_integrations.py b/tests/test_integrations.py index 915a82d59..8609920f1 100644 --- a/tests/test_integrations.py +++ b/tests/test_integrations.py @@ -329,6 +329,22 @@ f "hello\n", 0, ), + # test system exit in unthreadable alias (see #5689) + ( + """ +from xonsh.tools import unthreadable + +@unthreadable +def _f(): + import sys + sys.exit(42) + +aliases['f'] = _f +print(![f].returncode) +""", + "42\n", + 0, + ), # test ambiguous globs ( """ diff --git a/xonsh/procs/proxies.py b/xonsh/procs/proxies.py index 6796b77fb..0fd29bafe 100644 --- a/xonsh/procs/proxies.py +++ b/xonsh/procs/proxies.py @@ -792,6 +792,10 @@ class ProcProxy: "stack": spec.stack, }, ) + except SystemExit as e: + # the alias function is running in the main thread, so we need to + # catch SystemExit to prevent the entire shell from exiting (see #5689) + r = e.code if isinstance(e.code, int) else int(bool(e.code)) except Exception: xt.print_exception(source_msg="Exception in " + get_proc_proxy_name(self)) r = 1