xref: /xnu-11215.61.5/tests/pty_121077498.c (revision 4f1223e81cd707a65cc109d0b8ad6653699da3c4)
1*4f1223e8SApple OSS Distributions #include <util.h>
2*4f1223e8SApple OSS Distributions #include <stdlib.h>
3*4f1223e8SApple OSS Distributions #include <fcntl.h>
4*4f1223e8SApple OSS Distributions #include <termios.h>
5*4f1223e8SApple OSS Distributions #include <signal.h>
6*4f1223e8SApple OSS Distributions #include <darwintest.h>
7*4f1223e8SApple OSS Distributions #include <darwintest_multiprocess.h>
8*4f1223e8SApple OSS Distributions 
9*4f1223e8SApple OSS Distributions #define TEST_TIMEOUT    10
10*4f1223e8SApple OSS Distributions 
11*4f1223e8SApple OSS Distributions T_GLOBAL_META(
12*4f1223e8SApple OSS Distributions 	T_META_RUN_CONCURRENTLY(TRUE));
13*4f1223e8SApple OSS Distributions 
14*4f1223e8SApple OSS Distributions static void
sigio_handler(__unused int sig)15*4f1223e8SApple OSS Distributions sigio_handler(__unused int sig)
16*4f1223e8SApple OSS Distributions {
17*4f1223e8SApple OSS Distributions 	/* Do nothing; this should never actually be called. */
18*4f1223e8SApple OSS Distributions }
19*4f1223e8SApple OSS Distributions 
20*4f1223e8SApple OSS Distributions T_HELPER_DECL(pty_121077498_impl, "fork helper")
21*4f1223e8SApple OSS Distributions {
22*4f1223e8SApple OSS Distributions 	int primary, replica, flags;
23*4f1223e8SApple OSS Distributions 	char rname[128], c;
24*4f1223e8SApple OSS Distributions 	sigset_t sigio_set, received_set;
25*4f1223e8SApple OSS Distributions 
26*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(sigemptyset(&sigio_set), "sigemptyset");
27*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(sigaddset(&sigio_set, SIGIO), "sigaddset");
28*4f1223e8SApple OSS Distributions 
29*4f1223e8SApple OSS Distributions 	/*
30*4f1223e8SApple OSS Distributions 	 * New session, lose any existing controlling terminal and become
31*4f1223e8SApple OSS Distributions 	 * session leader.
32*4f1223e8SApple OSS Distributions 	 */
33*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(setsid(), NULL);
34*4f1223e8SApple OSS Distributions 
35*4f1223e8SApple OSS Distributions 	/* Open the primary side, following `openpty`'s implementation. */
36*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(primary = posix_openpt(O_RDWR | O_NOCTTY), NULL);
37*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(grantpt(primary), NULL);
38*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(unlockpt(primary), NULL);
39*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ptsname_r(primary, rname, sizeof(rname)), NULL);
40*4f1223e8SApple OSS Distributions 
41*4f1223e8SApple OSS Distributions 	/* Enable both O_NONBLOCK and O_ASYNC before opening the replica. */
42*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(flags = fcntl(primary, F_GETFL, 0), NULL);
43*4f1223e8SApple OSS Distributions 	flags |= O_NONBLOCK | O_ASYNC;
44*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(flags = fcntl(primary, F_SETFL, flags), NULL);
45*4f1223e8SApple OSS Distributions 
46*4f1223e8SApple OSS Distributions 	/* Open the replica, making it our controlling terminal. */
47*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(replica = open(rname, O_RDWR, 0), "open %s", rname);
48*4f1223e8SApple OSS Distributions 
49*4f1223e8SApple OSS Distributions 	/* Verify that we are non-blocking. */
50*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_FAILURE(read(primary, &c, 1), EAGAIN, "read with no data returns EAGAIN");
51*4f1223e8SApple OSS Distributions 
52*4f1223e8SApple OSS Distributions 	/* Set us up to detect when we get a SIGIO. */
53*4f1223e8SApple OSS Distributions 	T_EXPECT_TRUE(SIG_ERR != signal(SIGIO, sigio_handler), "set SIGIO handler");
54*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(sigprocmask(SIG_BLOCK, &sigio_set, NULL), "block SIGIO");
55*4f1223e8SApple OSS Distributions 
56*4f1223e8SApple OSS Distributions 	/* Flush the replica, which should trigger a SIGIO. */
57*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(tcflush(replica, TCIOFLUSH), NULL);
58*4f1223e8SApple OSS Distributions 
59*4f1223e8SApple OSS Distributions 	/* Verify that we got SIGIO. */
60*4f1223e8SApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(sigpending(&received_set), NULL);
61*4f1223e8SApple OSS Distributions 	T_ASSERT_TRUE(sigismember(&received_set, SIGIO), "received SIGIO when we flushed");
62*4f1223e8SApple OSS Distributions 
63*4f1223e8SApple OSS Distributions 	/* Reset state. */
64*4f1223e8SApple OSS Distributions 	T_EXPECT_TRUE(SIG_ERR != signal(SIGIO, SIG_IGN), "reset SIGIO handler");
65*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(sigprocmask(SIG_UNBLOCK, &sigio_set, NULL), "unblock SIGIO");
66*4f1223e8SApple OSS Distributions 
67*4f1223e8SApple OSS Distributions 	/* Close fds. */
68*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(close(replica), NULL);
69*4f1223e8SApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(close(primary), NULL);
70*4f1223e8SApple OSS Distributions }
71*4f1223e8SApple OSS Distributions 
72*4f1223e8SApple OSS Distributions T_DECL(pty_121077498, "Ability to use O_NONBLOCK and O_ASYNC on pty primary without replica open.")
73*4f1223e8SApple OSS Distributions {
74*4f1223e8SApple OSS Distributions 	/*
75*4f1223e8SApple OSS Distributions 	 * We need to do the test in a child process because we might have
76*4f1223e8SApple OSS Distributions 	 * getpgrp() == getpid().
77*4f1223e8SApple OSS Distributions 	 */
78*4f1223e8SApple OSS Distributions 	dt_helper_t helper = dt_child_helper("pty_121077498_impl");
79*4f1223e8SApple OSS Distributions 	dt_run_helpers(&helper, 1, TEST_TIMEOUT);
80*4f1223e8SApple OSS Distributions }
81