diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ef4e31403198..2324bd3986ae 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -205,6 +205,7 @@ Guidelines for modifications: * Xu Li * Yang Jin * Yanzi Zhu +* Yichao Gan * Yijie Guo * Yize Wang * Yohan Choi diff --git a/source/isaaclab/changelog.d/rx-02333-fix-sigterm-shutdown.rst b/source/isaaclab/changelog.d/rx-02333-fix-sigterm-shutdown.rst new file mode 100644 index 000000000000..627ec7765cae --- /dev/null +++ b/source/isaaclab/changelog.d/rx-02333-fix-sigterm-shutdown.rst @@ -0,0 +1,5 @@ +Fixed +^^^^^ + +* Fixed :class:`~isaaclab.app.AppLauncher` leaving Python processes + running after receiving ``SIGTERM``. diff --git a/source/isaaclab/isaaclab/app/app_launcher.py b/source/isaaclab/isaaclab/app/app_launcher.py index fdb3f321900b..207d60cd20f2 100644 --- a/source/isaaclab/isaaclab/app/app_launcher.py +++ b/source/isaaclab/isaaclab/app/app_launcher.py @@ -332,7 +332,7 @@ def _atexit_close(app=self._app): # Set up signal handlers for graceful shutdown # -- during explicit `kill` commands - signal.signal(signal.SIGTERM, self._abort_signal_handle_callback) + signal.signal(signal.SIGTERM, self._terminate_signal_handle_callback) # -- during aborts signal.signal(signal.SIGABRT, self._abort_signal_handle_callback) # -- during segfaults @@ -1376,6 +1376,11 @@ def _interrupt_signal_handle_callback(self, signal, frame): # raise the error for keyboard interrupt raise KeyboardInterrupt + @staticmethod + def _terminate_signal_handle_callback(signum, _frame): + """Terminate the process while preserving Python cleanup handlers.""" + raise SystemExit(128 + signum) + def is_isaac_sim_version_5(self) -> bool: if not hasattr(self, "_is_sim_ver_5"): # 1) Try to read the VERSION file (for manual / binary installs) diff --git a/source/isaaclab/test/app/test_signal_handling.py b/source/isaaclab/test/app/test_signal_handling.py new file mode 100644 index 000000000000..481434e5cbc1 --- /dev/null +++ b/source/isaaclab/test/app/test_signal_handling.py @@ -0,0 +1,18 @@ +# Copyright (c) 2022-2026, The Isaac Lab Project Developers (https://github.com/isaac-sim/IsaacLab/blob/main/CONTRIBUTORS.md). +# All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +import signal + +import pytest + +from isaaclab.app import AppLauncher + + +def test_sigterm_handler_terminates_process(): + """SIGTERM must terminate Python instead of resuming after the handler.""" + with pytest.raises(SystemExit) as exc_info: + AppLauncher._terminate_signal_handle_callback(signal.SIGTERM, None) + + assert exc_info.value.code == 128 + signal.SIGTERM