master
c 293 lines 8.22 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 select.c
8
9 Abstract:
10
11 This file is the select system call test.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <sys/select.h>
18 #include <sys/stat.h>
19 #include <sys/time.h>
20 #include <sys/resource.h>
21 #include <sys/types.h>
22 #include <sys/mman.h>
23 #include <unistd.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <stdlib.h>
27
28 #if defined(__aarch64__)
29
30 //
31 // ARM64 glibc converts select to pselect.
32 //
33
34 #define __ARCH_WANT_SYSCALL_DEPRECATED
35 #include <linux/unistd.h>
36 #define SYS_select __NR_select
37 #endif
38
39 #define LxtSelect(_nfds, _readfds, _writefds, _exceptfds, _timeout) \
40 (syscall(SYS_select, _nfds, _readfds, _writefds, _exceptfds, _timeout))
41
42 #define LXT_NAME "Select"
43 #define LXT_SELECT_TEST_FILE "/data/test/select_test.bin"
44 #define LXT_SHORT_TIMEOUT 1
45
46 LXT_VARIATION_HANDLER SelectFdBufferSize;
47 LXT_VARIATION_HANDLER SelectMaxNfds;
48
49 //
50 // Global constants
51 //
52
53 static const LXT_VARIATION g_LxtVariations[] = {{"FD buffer sizes", SelectFdBufferSize}, {"Max nfds", SelectMaxNfds}};
54
55 int SelectTestEntry(int Argc, char* Argv[])
56
57 /*++
58 --*/
59
60 {
61
62 LXT_ARGS Args;
63 int Result;
64
65 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
66 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
67
68 ErrorExit:
69 LxtUninitialize();
70 return !LXT_SUCCESS(Result);
71 }
72
73 int SelectFdBufferSize(PLXT_ARGS Args)
74 {
75
76 unsigned char* Address;
77 int Fds[sizeof(unsigned long) * 8 * 2];
78 int Index;
79 void* MapResult;
80 int Result;
81 fd_set* ReadSet;
82 unsigned char* ReadSetBuffer;
83 int ReadSetCount;
84 struct timeval Timeout;
85
86 Address = NULL;
87 memset(Fds, -1, sizeof(Fds));
88 Result = LXT_RESULT_FAILURE;
89
90 //
91 // Open files that will be used for select.
92 //
93
94 for (Index = 0; Index < LXT_COUNT_OF(Fds); ++Index)
95 {
96 LxtCheckErrno(Fds[Index] = open(LXT_SELECT_TEST_FILE, O_RDWR | O_CREAT, S_IRWXU));
97 }
98
99 //
100 // Create a read\write page followed by a no access page. The readset buffer
101 // will be adjusted so it is just before the no access page.
102 //
103
104 LxtCheckMapErrno(Address = mmap(NULL, PAGE_SIZE * 2, (PROT_READ | PROT_WRITE), (MAP_PRIVATE | MAP_ANONYMOUS), -1, 0));
105 LxtCheckErrno(mprotect(Address + PAGE_SIZE, PAGE_SIZE, PROT_NONE));
106
107 //
108 // A ReadSetCount of 0 should not touch the buffer.
109 //
110
111 ReadSetCount = 0;
112 ReadSetBuffer = (Address + PAGE_SIZE) - sizeof(unsigned char);
113 memset(ReadSetBuffer, -1, sizeof(unsigned char));
114 ReadSet = (fd_set*)ReadSetBuffer;
115 memset(&Timeout, 0, sizeof(Timeout));
116 LxtCheckErrno(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout));
117 LxtCheckEqual(*ReadSetBuffer, (unsigned char)-1, "%c");
118
119 //
120 // Test select with different sized buffers that have all of the bits set
121 // and a ReadSetCount of 1. The expectation is that the write will fail if
122 // the buffer is less than an unsigned long. If larger, the values will be
123 // zeroed out to an unsigned long but not more.
124 //
125
126 ReadSetCount = 1;
127 ReadSetBuffer = (Address + PAGE_SIZE) - sizeof(unsigned char);
128 memset(ReadSetBuffer, -1, sizeof(unsigned char));
129 ReadSet = (fd_set*)ReadSetBuffer;
130 memset(&Timeout, 0, sizeof(Timeout));
131 LxtCheckErrnoFailure(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout), EFAULT);
132 LxtCheckEqual(*ReadSetBuffer, (unsigned char)-1, "%c");
133
134 if (sizeof(unsigned int) != sizeof(unsigned long))
135 {
136 ReadSetBuffer = (Address + PAGE_SIZE) - sizeof(unsigned int);
137 memset(ReadSetBuffer, -1, sizeof(unsigned int));
138 ReadSet = (fd_set*)ReadSetBuffer;
139 memset(&Timeout, 0, sizeof(Timeout));
140 LxtCheckErrnoFailure(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout), EFAULT);
141 LxtCheckEqual(*(unsigned int*)ReadSetBuffer, (unsigned int)-1, "%d");
142 }
143
144 ReadSetBuffer = (Address + PAGE_SIZE) - sizeof(unsigned long);
145 memset(ReadSetBuffer, -1, sizeof(unsigned long));
146 ReadSet = (fd_set*)ReadSetBuffer;
147 memset(&Timeout, 0, sizeof(Timeout));
148 LxtCheckErrno(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout));
149 LxtCheckEqual(*((unsigned long*)ReadSetBuffer), 0, "%ld");
150
151 ReadSetBuffer = (Address + PAGE_SIZE) - (sizeof(unsigned long) * 2);
152 memset(ReadSetBuffer, -1, sizeof(unsigned long) * 2);
153 ReadSet = (fd_set*)ReadSetBuffer;
154 memset(&Timeout, 0, sizeof(Timeout));
155 LxtCheckErrno(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout));
156 LxtCheckEqual(*((unsigned long*)ReadSetBuffer), 0, "%ld");
157 LxtCheckEqual(*(((unsigned long*)ReadSetBuffer + 1)), -1, "%ld");
158
159 //
160 // Test with a ReadSetCount of exactly the number of bits in an unsigned
161 // long.
162 //
163
164 ReadSetCount = sizeof(unsigned long) * 8;
165 ReadSetBuffer = (Address + PAGE_SIZE) - (sizeof(unsigned long) * 2);
166 memset(ReadSetBuffer, -1, sizeof(unsigned long) * 2);
167 ReadSet = (fd_set*)ReadSetBuffer;
168 memset(&Timeout, 0, sizeof(Timeout));
169 LxtCheckErrno(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout));
170 LxtCheckNotEqual(*((unsigned long*)ReadSetBuffer), -1, "%ld");
171 LxtCheckEqual(*(((unsigned long*)ReadSetBuffer + 1)), -1, "%ld");
172
173 //
174 // And again with one larger.
175 //
176
177 ReadSetCount = sizeof(unsigned long) * 8 + 1;
178 ReadSetBuffer = (Address + PAGE_SIZE) - (sizeof(unsigned long) * 2);
179 memset(ReadSetBuffer, -1, sizeof(unsigned long) * 2);
180 ReadSet = (fd_set*)ReadSetBuffer;
181 memset(&Timeout, 0, sizeof(Timeout));
182 LxtCheckErrno(LxtSelect(ReadSetCount, ReadSet, NULL, NULL, &Timeout));
183 LxtCheckNotEqual(*((unsigned long*)ReadSetBuffer), -1, "%ld");
184 LxtCheckEqual(*(((unsigned long*)ReadSetBuffer + 1)), 1, "%ld");
185
186 Result = LXT_RESULT_SUCCESS;
187
188 ErrorExit:
189 for (Index = 0; Index < LXT_COUNT_OF(Fds); ++Index)
190 {
191 if (Fds[Index] != -1)
192 {
193 LxtClose(Fds[Index]);
194 }
195 }
196
197 if (Address != NULL)
198 {
199 munmap(Address, PAGE_SIZE * 2);
200 }
201
202 return Result;
203 }
204
205 int SelectMaxNfds(PLXT_ARGS Args)
206 {
207
208 int Result;
209 int Fd;
210 int NumFd;
211 fd_set ReadSet;
212 struct timeval Timeout;
213 struct rlimit MaxFds;
214
215 //
216 // Initialize locals.
217 //
218
219 Fd = -1;
220 Timeout.tv_sec = 5;
221 Timeout.tv_usec = 0;
222
223 //
224 // Open a file that will be used for select.
225 //
226
227 LxtCheckErrno(Fd = open(LXT_SELECT_TEST_FILE, (O_RDWR | O_CREAT), S_IRWXU));
228
229 //
230 // Create the select set and set the FD in it.
231 //
232
233 FD_ZERO(&ReadSet);
234 FD_SET(Fd, &ReadSet);
235
236 //
237 // -ve values for 'nfds' should return EINVAL.
238 //
239
240 LxtCheckErrnoFailure(select(-1, &ReadSet, NULL, NULL, &Timeout), EINVAL);
241
242 LxtLogInfo("Waiting on select to succeed..");
243
244 //
245 // Set 'nfds' to > FD_SETSIZE. Kernel seems to ignore anything above the
246 // current ulimit(RLIMIT_NOFILE).
247 //
248 // N.B The value chosen for 'nfds' is > nr_open (which is the upper limit
249 // for RLIMIT_NOFILE and by default set to 1048576). As per the man
250 // page, EINVAL is returned if nfds exceeds the RLIMIT_NOFILE resource
251 // limit, but that doesn't seem to be case.
252 //
253
254 LxtCheckErrno(NumFd = select(1048576 + 100, &ReadSet, NULL, NULL, &Timeout));
255
256 LxtCheckEqual(NumFd, 1, "%d");
257 if (FD_ISSET(Fd, &ReadSet) == 0)
258 {
259 LxtLogError(
260 "Select was satisfied but file descriptor is not set "
261 "for read!");
262
263 Result = -1;
264 goto ErrorExit;
265 }
266
267 //
268 // Provide a bad file descriptor to select. As per the man page kernel
269 // ignores any FD > maximum FD currently opened by the process. But,
270 // in testing it seems like it does perform that check.
271 //
272 // N.B Below assumes that 200 > #FD's opened by the process.
273 //
274
275 FD_ZERO(&ReadSet);
276 FD_SET(200, &ReadSet);
277
278 //
279 // Kernel ignores anything above FD_SETSIZE.
280 //
281
282 LxtCheckErrnoFailure(select(201, &ReadSet, NULL, NULL, &Timeout), EBADF);
283
284 Result = LXT_RESULT_SUCCESS;
285
286 ErrorExit:
287 if (Fd != -1)
288 {
289 close(Fd);
290 }
291
292 return Result;
293 }