1 /* Copyright (C) 2006-2022 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, see
16 <https://www.gnu.org/licenses/>. */
17
18 #include <errno.h>
19 #include <intprops.h>
20 #include <support/check.h>
21 #include <support/support.h>
22 #include <support/xsignal.h>
23 #include <support/xunistd.h>
24 #include <support/xtime.h>
25 #include <stdlib.h>
26
27 static volatile int handler_called;
28
29 static void
handler(int sig)30 handler (int sig)
31 {
32 handler_called = 1;
33 }
34
35
36 static void
test_pselect_basic(void)37 test_pselect_basic (void)
38 {
39 struct sigaction sa;
40 sa.sa_handler = handler;
41 sa.sa_flags = 0;
42 sigemptyset (&sa.sa_mask);
43
44 xsigaction (SIGUSR1, &sa, NULL);
45
46 sa.sa_handler = SIG_IGN;
47 xsigaction (SIGCHLD, &sa, NULL);
48
49 sigset_t ss_usr1;
50 sigemptyset (&ss_usr1);
51 sigaddset (&ss_usr1, SIGUSR1);
52 TEST_COMPARE (sigprocmask (SIG_BLOCK, &ss_usr1, NULL), 0);
53
54 int fds[2][2];
55 xpipe (fds[0]);
56 xpipe (fds[1]);
57
58 fd_set rfds;
59 FD_ZERO (&rfds);
60
61 sigset_t ss;
62 TEST_COMPARE (sigprocmask (SIG_SETMASK, NULL, &ss), 0);
63 sigdelset (&ss, SIGUSR1);
64
65 struct timespec to = { .tv_sec = 0, .tv_nsec = 500000000 };
66
67 pid_t parent = getpid ();
68 pid_t p = xfork ();
69 if (p == 0)
70 {
71 xclose (fds[0][1]);
72 xclose (fds[1][0]);
73
74 FD_SET (fds[0][0], &rfds);
75
76 int e;
77 do
78 {
79 if (getppid () != parent)
80 FAIL_EXIT1 ("getppid()=%d != parent=%d", getppid(), parent);
81
82 errno = 0;
83 e = pselect (fds[0][0] + 1, &rfds, NULL, NULL, &to, &ss);
84 }
85 while (e == 0);
86
87 TEST_COMPARE (e, -1);
88 TEST_COMPARE (errno, EINTR);
89
90 TEMP_FAILURE_RETRY (write (fds[1][1], "foo", 3));
91
92 exit (0);
93 }
94
95 xclose (fds[0][0]);
96 xclose (fds[1][1]);
97
98 FD_SET (fds[1][0], &rfds);
99
100 TEST_COMPARE (kill (p, SIGUSR1), 0);
101
102 int e = pselect (fds[1][0] + 1, &rfds, NULL, NULL, NULL, &ss);
103 TEST_COMPARE (e, 1);
104 TEST_VERIFY (FD_ISSET (fds[1][0], &rfds));
105 }
106
107 static void
test_pselect_large_timeout(void)108 test_pselect_large_timeout (void)
109 {
110 support_create_timer (0, 100000000, false, NULL);
111
112 int fds[2];
113 xpipe (fds);
114
115 fd_set rfds;
116 FD_ZERO (&rfds);
117 FD_SET (fds[0], &rfds);
118
119 sigset_t ss;
120 TEST_COMPARE (sigprocmask (SIG_SETMASK, NULL, &ss), 0);
121 sigdelset (&ss, SIGALRM);
122
123 struct timespec ts = { TYPE_MAXIMUM (time_t), 0 };
124
125 TEST_COMPARE (pselect (fds[0] + 1, &rfds, NULL, NULL, &ts, &ss), -1);
126 TEST_VERIFY (errno == EINTR || errno == EOVERFLOW);
127 }
128
129 static int
do_test(void)130 do_test (void)
131 {
132 test_pselect_basic ();
133
134 test_pselect_large_timeout ();
135
136 return 0;
137 }
138
139 #include <support/test-driver.c>
140