tests: Add Ctrl-C interrupt tests using extended repl_ framework#18435
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #18435 +/- ##
==========================================
+ Coverage 98.46% 98.47% +0.01%
==========================================
Files 176 176
Lines 22831 22831
==========================================
+ Hits 22480 22483 +3
+ Misses 351 348 -3 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
8c0c04a to
66d819f
Compare
|
@andrewleech please check CI here: ruff formatting, and the unix port macos seems to lockup during the tests. |
cfdbe88 to
001c59d
Compare
|
Code size report: |
|
Thanks @dpgeorge, both fixed now. Branch is rebased and split into two commits. The macOS hang is the same The test approach is also reworked. The controlling terminal setup ( Also dropped |
5db8be3 to
dcc243d
Compare
|
Thanks for updating. I've rerun the unix CI on this PR 10 times now, to test reliability. Over those 10 runs I saw only one error, on the unix qemu_arm job running the tests, On other PRs I do sometimes see failures with |
|
I've seen a few jobs intermittently fail still, often possibly related to the load on the ci servers at the time, eg. #19103 Though considering repl_emacs_keys.py doesn't have a timing / timeout loop that doesn't seem as likely the cause here. |
Change tcsetattr from TCSAFLUSH to TCSANOW in mp_hal_stdio_mode_raw and mp_hal_stdio_mode_orig. The TCSAFLUSH flag calls tcdrain() before applying terminal settings, which blocks indefinitely on macOS when used with PTY devices if the master side has not read all pending output. This is a known macOS kernel behavior (XNU ttywait loops until the output queue is consumed by the master). The drain serves no practical purpose on the unix port since output is written via write() syscalls that complete before tcsetattr is called. The input flush is also unnecessary since MicroPython's readline handles stale input gracefully. Two repl_ test .exp files are updated to account for the newline after Ctrl-D (end paste mode) no longer being discarded by the input flush; it produces an extra empty prompt line. Signed-off-by: Andrew Leech <[email protected]>
Adds a "# sigint:" directive for repl_ tests that need Ctrl-C to generate SIGINT via the PTY terminal driver. When present, the child process is set up with the PTY as its controlling terminal (via setsid/TIOCSCTTY/tcsetpgrp) so that \x03 written to the PTY master generates SIGINT for the child's process group. This works because MicroPython's REPL restores original terminal settings (with ISIG enabled) before executing user code, allowing the terminal driver to convert \x03 into SIGINT during blocking operations. Test added: - repl_ctrl_c_interrupt_execution.py: Verifies Ctrl-C interrupts a blocking time.sleep() call and the REPL remains functional afterward. Also wraps PTY fd handling in try/finally for all repl_ tests. Signed-off-by: Andrew Leech <[email protected]>
Summary
This PR adds Unix port test coverage for Ctrl-C (SIGINT) interrupt handling in MicroPython's REPL by extending the existing
repl_test framework to support signal generation through proper PTY configuration.The framework now configures terminal attributes to enable signal generation (ISIG flag) and sets up the PTY as the controlling terminal for the MicroPython subprocess, allowing
{\x03}sequences in test files to trigger actual SIGINT delivery rather than just sending the byte.Two test cases cover the critical interrupt scenarios:
time.sleep())Testing
Tested on Linux (Unix port) with the new test files:
tests/cmdline/repl_ctrl_c_paste_cancel.py- verifies Ctrl-C exits paste mode cleanlytests/cmdline/repl_ctrl_c_interrupt_execution.py- verifies Ctrl-C raises KeyboardInterrupt during executionBoth tests pass and demonstrate correct signal handling and REPL recovery.
The changes are isolated to the Unix port's test infrastructure and gracefully skip on platforms without PTY support (already handled by existing Windows/msys/cygwin detection).
Trade-offs and Alternatives
Added a try/finally block around PTY usage which increases indentation depth slightly, but this ensures proper cleanup of file descriptors even if subprocess creation fails.
The
normalize_newlines()function handles the PTY double-newline quirk (\r\r\n) which may be platform-specific, but the extra replacement pass has negligible performance impact in the test suite.