@@ -2159,6 +2159,60 @@ TEST_F(JobControlTest, ReuseControllingTTYAfterExit) {
21592159 ASSERT_NO_ERRNO (res2);
21602160}
21612161
2162+ // When ISIG is disabled, signal characters (Ctrl-C, Ctrl-Z, Ctrl-\) should
2163+ // be passed through to the reader as ordinary characters, not generate signals.
2164+ // This matches Linux n_tty.c behavior: signal chars are only special when
2165+ // L_ISIG(tty) is true.
2166+ TEST_F (PtyTest, SignalCharPassedThroughWhenISIGDisabled) {
2167+ // Disable ISIG.
2168+ struct kernel_termios t = {};
2169+ EXPECT_THAT (ioctl (replica_.get (), TCGETS , &t), SyscallSucceeds ());
2170+ t.c_lflag &= ~ISIG ;
2171+ // Also disable ICANON so we can read character by character.
2172+ t.c_lflag &= ~ICANON ;
2173+ t.c_cc [VMIN ] = 1 ;
2174+ t.c_cc [VTIME ] = 0 ;
2175+ EXPECT_THAT (ioctl (replica_.get (), TCSETS , &t), SyscallSucceeds ());
2176+
2177+ // Write Ctrl-C to master.
2178+ constexpr char kCtrlC = ControlCharacter (' C' );
2179+ ASSERT_THAT (WriteFd (master_.get (), &kCtrlC , 1 ), SyscallSucceedsWithValue (1 ));
2180+
2181+ // The signal character should appear on the replica as a normal byte.
2182+ char buf = 0 ;
2183+ ASSERT_NO_ERRNO (WaitUntilReceived (replica_.get (), 1 ));
2184+ ASSERT_THAT (ReadFd (replica_.get (), &buf, 1 ), SyscallSucceedsWithValue (1 ));
2185+ EXPECT_EQ (buf, kCtrlC );
2186+ }
2187+
2188+ // When ISIG is enabled (default), signal characters should be consumed and
2189+ // NOT passed to the reading process. In Linux, n_tty_receive_signal_char()
2190+ // calls n_tty_flush_buffer_and_wake() which prevents the character from
2191+ // appearing in the read buffer.
2192+ TEST_F (PtyTest, SignalCharConsumedWhenISIGEnabled) {
2193+ // Ensure ISIG is enabled (it should be by default).
2194+ struct kernel_termios t = {};
2195+ EXPECT_THAT (ioctl (replica_.get (), TCGETS , &t), SyscallSucceeds ());
2196+ t.c_lflag |= ISIG ;
2197+ // Disable ICANON for raw reading.
2198+ t.c_lflag &= ~ICANON ;
2199+ t.c_cc [VMIN ] = 1 ;
2200+ t.c_cc [VTIME ] = 0 ;
2201+ EXPECT_THAT (ioctl (replica_.get (), TCSETS , &t), SyscallSucceeds ());
2202+
2203+ // Write Ctrl-C followed by a normal character.
2204+ constexpr char kInput [] = {ControlCharacter (' C' ), ' a' };
2205+ ASSERT_THAT (WriteFd (master_.get (), kInput , sizeof (kInput )),
2206+ SyscallSucceedsWithValue (sizeof (kInput )));
2207+
2208+ // Only the normal character 'a' should be readable; Ctrl-C should have been
2209+ // consumed by the signal delivery path.
2210+ char buf = 0 ;
2211+ ASSERT_NO_ERRNO (WaitUntilReceived (replica_.get (), 1 ));
2212+ ASSERT_THAT (ReadFd (replica_.get (), &buf, 1 ), SyscallSucceedsWithValue (1 ));
2213+ EXPECT_EQ (buf, ' a' );
2214+ }
2215+
21622216} // namespace
21632217} // namespace testing
21642218} // namespace gvisor
0 commit comments