Skip to content

fix: add SIGINT signal handler for reliable Ctrl+C experiment abort#1504

Merged
SAKURA-CAT merged 3 commits intoSwanHubX:mainfrom
hhe48203-ctrl:fix/issue-1329-ctrl-c-signal-handler
Mar 17, 2026
Merged

fix: add SIGINT signal handler for reliable Ctrl+C experiment abort#1504
SAKURA-CAT merged 3 commits intoSwanHubX:mainfrom
hhe48203-ctrl:fix/issue-1329-ctrl-c-signal-handler

Conversation

@hhe48203-ctrl
Copy link
Copy Markdown
Contributor

Summary

  • Register a signal.SIGINT handler alongside the existing sys.excepthook to reliably detect Ctrl+C
  • sys.excepthook alone fails when the main thread is blocked in C extensions (NumPy, PyTorch, etc.), causing experiments to miss the "aborted" state
  • The SIGINT handler calls finish(state="aborted"), restores the original handler, and re-raises the signal for normal process termination
  • Handler is properly cleaned up in _cleanup() to avoid leaking into user code after the run ends

Changes

  • swanlab/sdk/internal/run/__init__.py: Added _sigint_handler method, SIGINT registration in __init__, and restoration in _cleanup
  • tests/unit/sdk/internal/run/test_finish_hook.py: Added 3 test cases covering running state, non-running state, and original callable handler delegation

Testing

  • All 10 existing + new unit tests pass
  • New tests cover: SIGINT during active run, SIGINT after run finished, original handler forwarding

Fixes #1329

sys.excepthook alone cannot reliably catch KeyboardInterrupt when the
main thread is blocked in C extensions (NumPy/PyTorch). Register a
signal.SIGINT handler as an additional safety net to ensure experiments
are always marked as "aborted" on Ctrl+C.

Fixes SwanHubX#1329
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the robustness of experiment termination in SwanLab by introducing a dedicated SIGINT signal handler. Previously, relying solely on sys.excepthook could lead to experiments failing to register as "aborted" if the main thread was blocked by C extensions (e.g., NumPy, PyTorch). The new handler ensures that Ctrl+C reliably triggers an "aborted" state, improving the accuracy of experiment tracking and providing a more consistent user experience.

Highlights

  • Reliable Ctrl+C Abort: Implemented a signal.SIGINT handler to ensure experiments can be reliably aborted via Ctrl+C, addressing limitations of sys.excepthook when the main thread is blocked by C extensions.
  • Aborted State Handling: The new SIGINT handler calls finish(state="aborted", error="KeyboardInterrupt") when an experiment is running, marking its state correctly.
  • Original Handler Restoration: The handler restores the original SIGINT handler and re-raises the signal to allow for normal process termination.
  • Proper Cleanup: The registered SIGINT handler is properly unregistered during the _cleanup() process to prevent leakage into user code.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • swanlab/sdk/internal/run/init.py
    • Imported the signal module.
    • Registered a SIGINT handler in the __init__ method to catch Ctrl+C signals.
    • Implemented the _sigint_handler method to manage the experiment state upon receiving a SIGINT.
    • Ensured the original SIGINT handler is restored during the _cleanup process.
  • tests/unit/sdk/internal/run/test_finish_hook.py
    • Imported signal and pytest.
    • Added a new test class TestSigintHandler.
    • Included a test case to verify finish(state='aborted') is called when the experiment is running.
    • Added a test case to confirm no operation when the experiment is not running.
    • Implemented a test case to ensure the original callable handler is invoked.
Activity
  • Author implemented a SIGINT handler to address sys.excepthook limitations with Ctrl+C.
  • Author added 3 new unit tests covering running state, non-running state, and original handler delegation.
  • Author confirmed all existing and new unit tests pass.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a SIGINT signal handler to reliably mark experiments as 'aborted' when interrupted with Ctrl+C. This is a solid improvement, especially for cases where the main thread is blocked in C extensions. The implementation is clean and includes appropriate cleanup and unit tests.

I've found one potential issue in the signal handler's logic concerning how it chains to the original handler, specifically for the SIG_IGN case. I've left a specific comment with a suggested fix. Overall, this is a valuable change that enhances the robustness of the experiment lifecycle management.

When the original handler was SIG_IGN, the handler incorrectly raised
KeyboardInterrupt instead of silently returning. Simplify the logic to
explicitly handle SIG_IGN, callable handlers, and SIG_DFL separately.
Add test for SIG_IGN scenario.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@SAKURA-CAT
Copy link
Copy Markdown
Member

LGTM!

@SAKURA-CAT SAKURA-CAT added the 💪 enhancement New feature or request label Mar 17, 2026
Invoke the saved original excepthook (self._sys_origin_excepthook) instead of directly calling sys.__excepthook__, and make the KeyboardInterrupt log message clearer ("aborting run..."). Update unit tests to set and assert against the saved hook, rename tests for clarity, and add coverage to ensure an outer framework's hook is used (and the builtin is not called) as well as that internal errors still result in calling the saved hook.
@SAKURA-CAT SAKURA-CAT merged commit 9680dcf into SwanHubX:main Mar 17, 2026
18 checks passed
@SAKURA-CAT SAKURA-CAT mentioned this pull request Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

💪 enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

手动选择的实验中断中增加Ctrl+C支持

2 participants