summaryrefslogtreecommitdiffhomepage
path: root/test/syscalls/linux/pty.cc
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-08-24 16:43:51 -0700
committergVisor bot <gvisor-bot@google.com>2021-08-24 16:43:51 -0700
commit18beb67703aa1d7a682bd851894632f2d1a0a730 (patch)
tree169a42af5fe64e7c2529506d2a05c7d7c7b3bca8 /test/syscalls/linux/pty.cc
parent0c2b2dc752e626f86454455bd991766ebd68497b (diff)
parentce4e54186e7c4a59bcdd9a74d89c5d4c2a7174f9 (diff)
Merge pull request #6438 from gystemd:tcsetpgrp_SIGTTOU
PiperOrigin-RevId: 392774712
Diffstat (limited to 'test/syscalls/linux/pty.cc')
-rw-r--r--test/syscalls/linux/pty.cc78
1 files changed, 78 insertions, 0 deletions
diff --git a/test/syscalls/linux/pty.cc b/test/syscalls/linux/pty.cc
index 5ff1f12a0..c008c89e7 100644
--- a/test/syscalls/linux/pty.cc
+++ b/test/syscalls/linux/pty.cc
@@ -1640,6 +1640,84 @@ TEST_F(JobControlTest, DISABLED_SetForegroundProcessGroup) {
ASSERT_NO_ERRNO(res);
}
+// This test verifies if a SIGTTOU signal is sent to the calling process's group
+// when tcsetpgrp is called by a background process
+TEST_F(JobControlTest, SetForegroundProcessGroupSIGTTOUBackground) {
+ auto res = RunInChild([=]() {
+ TEST_PCHECK(setsid() >= 0);
+ TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
+ pid_t grandchild = fork();
+ if (!grandchild) {
+ // Assign a different pgid to the child so it will result as
+ // a background process.
+ TEST_PCHECK(!setpgid(grandchild, getpid()));
+ TEST_PCHECK(!tcsetpgrp(replica_.get(), getpgid(0)));
+ // We should never reach this.
+ _exit(1);
+ }
+ int wstatus;
+ TEST_PCHECK(waitpid(grandchild, &wstatus, WSTOPPED) == grandchild);
+ TEST_PCHECK(WSTOPSIG(wstatus) == SIGTTOU);
+ });
+ ASSERT_NO_ERRNO(res);
+}
+
+// This test verifies that a SIGTTOU signal is not delivered to
+// a background process which calls tcsetpgrp and is ignoring SIGTTOU
+TEST_F(JobControlTest, SetForegroundProcessGroupSIGTTOUIgnored) {
+ auto res = RunInChild([=]() {
+ TEST_PCHECK(setsid() >= 0);
+ TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
+ pid_t grandchild = fork();
+ if (!grandchild) {
+ // Ignore SIGTTOU so the child in background won't
+ // be stopped when it will call tcsetpgrp
+ struct sigaction sa = {};
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGTTOU, &sa, NULL);
+ // Assign a different pgid to the child so it will result as
+ // a background process.
+ TEST_PCHECK(!setpgid(grandchild, getpid()));
+ TEST_PCHECK(!tcsetpgrp(replica_.get(), getpgid(0)));
+ _exit(0);
+ }
+ int wstatus;
+ TEST_PCHECK(waitpid(grandchild, &wstatus, WSTOPPED) == grandchild);
+ TEST_PCHECK(WSTOPSIG(wstatus) != SIGTTOU);
+ TEST_PCHECK(WIFEXITED(wstatus));
+ });
+ ASSERT_NO_ERRNO(res);
+}
+
+// This test verifies that a SIGTTOU signal is not delivered to
+// a background process which calls tcsetpgrp and is blocking SIGTTOU
+TEST_F(JobControlTest, SetForegroundProcessGroupSIGTTOUBlocked) {
+ auto res = RunInChild([=]() {
+ TEST_PCHECK(setsid() >= 0);
+ TEST_PCHECK(!ioctl(replica_.get(), TIOCSCTTY, 0));
+ pid_t grandchild = fork();
+ if (!grandchild) {
+ // Block SIGTTOU so the child in background won't
+ // be stopped when it will call tcsetpgrp
+ sigset_t signal_set;
+ sigemptyset(&signal_set);
+ sigaddset(&signal_set, SIGTTOU);
+ sigprocmask(SIG_BLOCK, &signal_set, NULL);
+ // Assign a different pgid to the child so it will result as
+ // a background process.
+ TEST_PCHECK(!setpgid(grandchild, getpid()));
+ TEST_PCHECK(!tcsetpgrp(replica_.get(), getpgid(0)));
+ _exit(0);
+ }
+ int wstatus;
+ TEST_PCHECK(waitpid(grandchild, &wstatus, WSTOPPED) == grandchild);
+ TEST_PCHECK(WSTOPSIG(wstatus) != SIGTTOU);
+ });
+ ASSERT_NO_ERRNO(res);
+}
+
TEST_F(JobControlTest, SetForegroundProcessGroupWrongTTY) {
pid_t pid = getpid();
ASSERT_THAT(ioctl(replica_.get(), TIOCSPGRP, &pid),