master
c 3,400 lines 90.2 KB
Raw
1 /*++
2
3 Copyright (c) Microsoft. All rights reserved.
4
5 Module Name:
6
7 epoll.c
8
9 Abstract:
10
11 This file is the epoll test.
12
13 --*/
14
15 #include "lxtcommon.h"
16 #include "unittests.h"
17 #include <sys/epoll.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <poll.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <sys/socket.h>
28 #include <sys/un.h>
29 #include <netinet/in.h>
30 #include <netdb.h>
31 #include "common.h"
32
33 #include <sys/wait.h>
34
35 #define LXT_NAME "Epoll"
36 #define SOCKET_NAME "PartyInTheUsa"
37 #define EPOLL_DUP2_FD_COUNT 100
38
39 typedef struct _EPOLL_DUP2_CONTEXT
40 {
41 int EpollFd;
42 int Fd[EPOLL_DUP2_FD_COUNT];
43 } EPOLL_DUP2_CONTEXT, *PEPOLL_DUP2_CONTEXT;
44
45 LXT_VARIATION_HANDLER EpollAddTest;
46 LXT_VARIATION_HANDLER EpollBasic;
47
48 int EpollBasicVariation(unsigned short ReadFlags, unsigned short WriteFlags);
49
50 LXT_VARIATION_HANDLER EpollDeleteCloseFdLoop;
51 LXT_VARIATION_HANDLER EpollDeleteTest;
52 LXT_VARIATION_HANDLER EpollDup2FdLoop;
53 LXT_VARIATION_HANDLER EpollHangupTestSimple;
54 LXT_VARIATION_HANDLER EpollHangupTestUnix;
55 LXT_VARIATION_HANDLER PPollInvalidArgument;
56 LXT_VARIATION_HANDLER EpollModifyWhilePollingTest;
57 LXT_VARIATION_HANDLER EpollModTest;
58 LXT_VARIATION_HANDLER EpollPhantomEventsTest;
59 LXT_VARIATION_HANDLER EpollRecursionTest;
60 LXT_VARIATION_HANDLER EpollRecursionLimitTest;
61 LXT_VARIATION_HANDLER EpollRelatedFileStress;
62 LXT_VARIATION_HANDLER EpollSequenceTestUnix;
63 LXT_VARIATION_HANDLER EpollSocketAcceptTest;
64 LXT_VARIATION_HANDLER EpollSocketReadTest;
65 LXT_VARIATION_HANDLER EpollUnalignedTest;
66 LXT_VARIATION_HANDLER EpollVariation0;
67
68 //
69 // Global constants
70 //
71
72 static const LXT_VARIATION g_LxtVariations[] = {
73 {"Basic_Variations", EpollBasic},
74 {"Epoll", EpollVariation0},
75 {"Epoll_Read", EpollSocketReadTest},
76 {"Epoll_Hangup", EpollHangupTestSimple},
77 {"Epoll_Accept", EpollSocketAcceptTest},
78 {"Epoll_Add", EpollAddTest},
79 {"Epoll_Delete", EpollDeleteTest},
80 {"Epoll_Modify_WhilePolling", EpollModifyWhilePollingTest},
81 {"Epoll_Related_File_Stress", EpollRelatedFileStress},
82 {"Epoll_Mod", EpollModTest},
83 {"Epoll_PhantomEvents", EpollPhantomEventsTest},
84 {"Ppoll invalid argument", PPollInvalidArgument},
85 {"Epoll unaligned", EpollUnalignedTest},
86 {"Epoll delete, close FD loop", EpollDeleteCloseFdLoop},
87 {"Epoll dup2 FD loop", EpollDup2FdLoop},
88 {"Epoll basic recursion", EpollRecursionTest},
89 {"Epoll recursion limit", EpollRecursionLimitTest}};
90
91 int EpollTestEntry(int Argc, char* Argv[])
92
93 /*++
94 --*/
95
96 {
97
98 LXT_ARGS Args;
99 int Result;
100
101 LxtCheckResult(LxtInitialize(Argc, Argv, &Args, LXT_NAME));
102 LXT_SYNCHRONIZATION_POINT_INIT();
103 LxtCheckResult(LxtRunVariations(&Args, g_LxtVariations, LXT_COUNT_OF(g_LxtVariations)));
104
105 ErrorExit:
106 LXT_SYNCHRONIZATION_POINT_DESTROY();
107 LxtUninitialize();
108 return !LXT_SUCCESS(Result);
109 }
110
111 #ifndef EPOLLONESHOT
112 #define EPOLLONESHOT (1 << 30)
113 #endif
114
115 int EpollBasic(PLXT_ARGS Args)
116
117 /*++
118 --*/
119
120 {
121 unsigned short ReadFlags[] = {EPOLLIN, EPOLLRDNORM, (EPOLLIN | EPOLLRDNORM)};
122 int ReadVariation;
123 int Result;
124 unsigned short WriteFlags[] = {EPOLLOUT, EPOLLWRNORM, (EPOLLOUT | EPOLLWRNORM)};
125 int WriteVariation;
126
127 for (ReadVariation = 0; ReadVariation < LXT_COUNT_OF(ReadFlags); ReadVariation += 1)
128 {
129
130 for (WriteVariation = 0; WriteVariation < LXT_COUNT_OF(ReadFlags); WriteVariation += 1)
131 {
132
133 Result = EpollBasicVariation(ReadFlags[ReadVariation], WriteFlags[WriteVariation]);
134
135 if (Result < 0)
136 {
137 LxtLogError("Failed basic variation (%d, %d)", ReadVariation, WriteVariation);
138
139 goto cleanup;
140 }
141 }
142 }
143
144 cleanup:
145 return Result;
146 }
147
148 int EpollBasicVariation(unsigned short ReadFlags, unsigned short WriteFlags)
149
150 /*++
151 --*/
152
153 {
154
155 struct epoll_event EpollControlEvent;
156 int EpollFileDescriptor;
157 struct epoll_event EpollWaitEvent[2];
158 struct epoll_event* InputEvent;
159 struct epoll_event* OutputEvent;
160 int PipeFileDescriptors[2] = {};
161 int Result;
162
163 //
164 // Initialize locals.
165 //
166
167 EpollFileDescriptor = -1;
168
169 //
170 // Open a pipe to test epoll.
171 //
172
173 LxtCheckErrnoZeroSuccess(pipe(PipeFileDescriptors));
174
175 //
176 // Pend a write.
177 //
178
179 LxtCheckErrno(write(PipeFileDescriptors[1], "\n", 1));
180
181 //
182 // Create an epoll.
183 //
184
185 LxtCheckErrno(EpollFileDescriptor = epoll_create(1));
186
187 //
188 // Add the file to the epoll.
189 //
190
191 EpollControlEvent.events = ReadFlags;
192 EpollControlEvent.data.fd = PipeFileDescriptors[0];
193 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
194
195 EpollControlEvent.events = WriteFlags | EPOLLPRI;
196 EpollControlEvent.data.fd = PipeFileDescriptors[1];
197 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, PipeFileDescriptors[1], &EpollControlEvent));
198
199 //
200 // Verify the epoll is triggered.
201 //
202
203 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 0));
204 if (Result != 2)
205 {
206 LxtLogError("Waiting on epoll returned %d events (expecting 2)!", Result);
207 Result = -1;
208 goto ErrorExit;
209 }
210
211 if (EpollWaitEvent[0].data.fd == PipeFileDescriptors[1])
212 {
213 InputEvent = &EpollWaitEvent[1];
214 OutputEvent = &EpollWaitEvent[0];
215 }
216 else
217 {
218 InputEvent = &EpollWaitEvent[0];
219 OutputEvent = &EpollWaitEvent[1];
220 }
221
222 LxtCheckEqual(InputEvent->data.fd, PipeFileDescriptors[0], "%d");
223 LxtCheckEqual(InputEvent->events, ReadFlags, "%hd");
224 LxtCheckEqual(OutputEvent->data.fd, PipeFileDescriptors[1], "%d");
225 LxtCheckEqual(OutputEvent->events, WriteFlags, "%hd");
226
227 ErrorExit:
228 if (EpollFileDescriptor != -1)
229 {
230 close(EpollFileDescriptor);
231 }
232
233 if (PipeFileDescriptors[1] != -1)
234 {
235 close(PipeFileDescriptors[1]);
236 }
237
238 if (PipeFileDescriptors[0] != -1)
239 {
240 close(PipeFileDescriptors[0]);
241 }
242
243 return Result;
244 }
245
246 int EpollCreateClientSocket(void)
247
248 /*++
249 --*/
250
251 {
252 int Result;
253 struct sockaddr_in ServerAddress = {0};
254 int Socket;
255
256 //
257 // Create a socket.
258 //
259
260 Socket = socket(AF_INET, SOCK_STREAM, 0);
261 if (Socket < 0)
262 {
263 LxtLogError("socket(AF_INET, SOCK_STREAM, 0) - %s", strerror(errno));
264 Result = -1;
265 goto cleanup;
266 }
267
268 //
269 // Connect to the server.
270 //
271
272 ServerAddress.sin_family = AF_INET;
273 ServerAddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
274 ServerAddress.sin_port = htons(LXT_SOCKET_DEFAULT_PORT);
275
276 Result = connect(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
277
278 if (Result < 0)
279 {
280 LxtLogError("connect(%d) - %s", Socket, strerror(errno));
281 Result = -1;
282 goto cleanup;
283 }
284
285 Result = Socket;
286 Socket = 0;
287
288 cleanup:
289 if (Socket > 0)
290 {
291 if (close(Socket) != 0)
292 {
293 LxtLogError("close(%d) - %s", Socket, strerror(errno));
294 Result = LXT_RESULT_FAILURE;
295 }
296 }
297
298 return Result;
299 }
300
301 int EpollCreateClientUnixSocket(int SocketType)
302
303 /*++
304 --*/
305
306 {
307 int Result;
308 struct sockaddr_un ServerAddress = {0};
309 int Socket;
310
311 //
312 // Create a socket.
313 //
314
315 Socket = socket(AF_UNIX, SocketType, 0);
316 if (Socket < 0)
317 {
318 LxtLogError("socket(AF_UNIX, SocketType, 0) - %s", strerror(errno));
319 Result = -1;
320 goto cleanup;
321 }
322
323 //
324 // Connect to the server.
325 //
326
327 ServerAddress.sun_family = AF_UNIX;
328 strcpy(ServerAddress.sun_path, SOCKET_NAME);
329
330 Result = connect(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
331
332 if (Result < 0)
333 {
334 LxtLogError("connect(%d) - %s", Socket, strerror(errno));
335 Result = -1;
336 goto cleanup;
337 }
338
339 Result = Socket;
340 Socket = 0;
341
342 cleanup:
343 if (Socket > 0)
344 {
345 if (close(Socket) != 0)
346 {
347 LxtLogError("close(%d) - %s", Socket, strerror(errno));
348 Result = LXT_RESULT_FAILURE;
349 }
350 }
351
352 return Result;
353 }
354
355 int EpollCreateListenSocket(void)
356
357 /*++
358 --*/
359
360 {
361
362 struct sockaddr_in ServerAddress = {0};
363 int Result;
364 int Socket;
365
366 //
367 // Create a socket.
368 //
369
370 Socket = socket(AF_INET, SOCK_STREAM, 0);
371 if (Socket < 0)
372 {
373 LxtLogError("socket - %s", strerror(errno));
374 Result = -1;
375 goto cleanup;
376 }
377
378 //
379 // Bind the socket to an ipv4 socket.
380 //
381
382 ServerAddress.sin_family = AF_INET;
383 ServerAddress.sin_addr.s_addr = INADDR_ANY;
384 ServerAddress.sin_port = htons(LXT_SOCKET_DEFAULT_PORT);
385
386 Result = bind(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
387
388 if (Result < 0)
389 {
390 LxtLogError("bind(%d) - %s", Socket, strerror(errno));
391 Result = -1;
392 goto cleanup;
393 }
394
395 //
396 // Mark the socket as a listen socket.
397 //
398
399 Result = listen(Socket, LXT_SOCKET_SERVER_MAX_BACKLOG_NUM);
400 if (Result < 0)
401 {
402 LxtLogError("listen(%d) - %s", Socket, strerror(errno));
403 Result = -1;
404 goto cleanup;
405 }
406
407 Result = Socket;
408 Socket = 0;
409
410 cleanup:
411
412 if (Socket > 0)
413 {
414 if (close(Socket) != 0)
415 {
416 LxtLogError("close(%d) - %s", Socket, strerror(errno));
417 }
418 }
419
420 return Result;
421 }
422
423 int EpollCreateListenUnixSocket(int SocketType)
424
425 /*++
426 --*/
427
428 {
429
430 struct sockaddr_un ServerAddress = {0};
431 int Result;
432 int Socket;
433
434 //
435 // Create a socket.
436 //
437
438 Socket = socket(AF_UNIX, SocketType, 0);
439 if (Socket < 0)
440 {
441 LxtLogError("socket - %s", strerror(errno));
442 Result = -1;
443 goto cleanup;
444 }
445
446 //
447 // Bind the socket to an ipv4 socket.
448 //
449
450 ServerAddress.sun_family = AF_UNIX;
451 strcpy(ServerAddress.sun_path, SOCKET_NAME);
452 unlink(SOCKET_NAME);
453 Result = bind(Socket, (struct sockaddr*)&ServerAddress, sizeof(ServerAddress));
454
455 if (Result < 0)
456 {
457 LxtLogError("bind(%d) - %s", Socket, strerror(errno));
458 Result = -1;
459 goto cleanup;
460 }
461
462 //
463 // Mark the socket as a listen socket.
464 //
465
466 Result = listen(Socket, LXT_SOCKET_SERVER_MAX_BACKLOG_NUM);
467 if (Result < 0)
468 {
469 LxtLogError("listen(%d) - %s", Socket, strerror(errno));
470 Result = -1;
471 goto cleanup;
472 }
473
474 Result = Socket;
475 Socket = 0;
476
477 cleanup:
478
479 if (Socket > 0)
480 {
481 if (close(Socket) != 0)
482 {
483 LxtLogError("close(%d) - %s", Socket, strerror(errno));
484 }
485 }
486
487 return Result;
488 }
489 int EpollHandleClientAccept(int Socket)
490
491 /*++
492 --*/
493
494 {
495
496 struct sockaddr_in ClientAddress = {0};
497 socklen_t ClientLength;
498 int ClientSocket;
499
500 ClientLength = sizeof(ClientAddress);
501 ClientSocket = accept(Socket, (struct sockaddr*)&ClientAddress, &ClientLength);
502 if (ClientSocket < 0)
503 {
504 LxtLogError("accept(%d) - %s", Socket, strerror(errno));
505 ClientSocket = -1;
506 goto cleanup;
507 }
508
509 cleanup:
510
511 return ClientSocket;
512 }
513
514 const char* DataToWrite[] = {
515 "<This is the first message> ",
516 "<This is another message> ",
517 "<Dumbledore is dead> ",
518 "<Harry Potter must not go back to Hogwarts> ",
519 "<There must always be a stark in Winterfell>",
520 };
521
522 const int WriteItemCount = sizeof(DataToWrite) / sizeof(DataToWrite[0]);
523
524 int EpollSocketReadTest(PLXT_ARGS Args)
525
526 /*++
527 --*/
528
529 {
530
531 char Buffer[256];
532 int Result;
533 int EpollFileDescriptor;
534 int FileDescriptor1;
535 int FileDescriptor2;
536 struct epoll_event EpollControlEvent;
537 struct epoll_event EpollWaitEvent[2];
538 int ChildPid;
539 int Index;
540 int ChildStatus;
541
542 //
543 // Initialize locals.
544 //
545
546 FileDescriptor1 = -1;
547 FileDescriptor2 = -1;
548 EpollFileDescriptor = -1;
549 ChildPid = -1;
550
551 //
552 // Create the server socket.
553 //
554
555 LxtLogInfo("[Setup] About to create server socket...");
556
557 FileDescriptor1 = EpollCreateListenSocket();
558 if (FileDescriptor1 == -1)
559 {
560 Result = errno;
561 LxtLogError("[Setup] Could not create socket! %d", Result);
562 goto cleanup;
563 }
564
565 //
566 // Fork to create a server and a client.
567 //
568
569 LxtLogInfo("[Setup] About to fork...");
570
571 ChildPid = fork();
572
573 if (ChildPid == -1)
574 {
575 Result = errno;
576 LxtLogError("[Setup] Fork failed! %d", Result);
577 goto cleanup;
578 }
579
580 if (ChildPid == 0)
581 {
582
583 LxtLogInfo("[Client] Waiting 2 seconds to let server block...");
584
585 usleep(2 * 1000 * 1000);
586
587 LxtLogInfo("[Client] Connecting to server...");
588
589 FileDescriptor2 = EpollCreateClientSocket();
590
591 LxtLogInfo("[Client] Connected to server, fd = %d", FileDescriptor2);
592
593 LxtLogInfo("[Client] Sleeping for 5 seconds with open socket");
594
595 usleep(5 * 1000 * 1000);
596
597 //
598 // Create an epoll container.
599 //
600
601 EpollFileDescriptor = epoll_create(1);
602
603 if (EpollFileDescriptor == -1)
604 {
605 Result = errno;
606 LxtLogError("[Client] Could not create Epoll! %d", Result);
607 goto cleanup;
608 }
609
610 //
611 // Add the connected socket to the epoll.
612 //
613
614 EpollControlEvent.events = EPOLLIN;
615 EpollControlEvent.data.fd = FileDescriptor2;
616
617 Result = epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor2, &EpollControlEvent);
618
619 if (Result == -1)
620 {
621 Result = errno;
622 LxtLogError("[Client] Could not add file to epoll! %d", Result);
623 goto cleanup;
624 }
625
626 //
627 // Wait for data to be available with a timeout.
628 //
629
630 while (1)
631 {
632
633 LxtLogInfo("[Client] Waiting on epoll with 15 second timeout ...");
634
635 Result = epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 15000);
636
637 LxtLogInfo("[Client] Epoll returned %d events", Result);
638
639 if (Result != 1)
640 {
641 LxtLogError("[Client] Wait on epoll failed! %d", Result);
642 Result = -1;
643 goto cleanup;
644 }
645
646 LxtLogInfo("[Client] Event: {%d, %x} ", EpollWaitEvent[0].data.fd, EpollWaitEvent[0].events);
647
648 if (EpollWaitEvent[0].data.fd != FileDescriptor2)
649 {
650 LxtLogError("[Client] Epoll wait satisfied with wrong user data! %d", EpollWaitEvent[0].data.fd);
651 Result = -1;
652 goto cleanup;
653 }
654
655 if (EpollWaitEvent[0].events != EPOLLIN)
656 {
657 LxtLogError("[Client] Epoll wait satisfied with wrong events! 0x%x", EpollWaitEvent[0].events);
658 Result = -1;
659 goto cleanup;
660 }
661
662 memset(Buffer, 0, sizeof(Buffer));
663 Result = read(FileDescriptor2, Buffer, sizeof(Buffer));
664 if (Result < 0)
665 {
666 Result = -1;
667 LxtLogError("[Client] Read on socket failed! %d", Result);
668 goto cleanup;
669 }
670
671 LxtLogInfo("[Client] read %d bytes: %s ...", Result, Buffer);
672
673 if (Result == 0)
674 {
675 LxtLogInfo("[Client] exiting ...");
676 goto cleanup;
677 }
678 }
679 }
680
681 //
682 // Accept an incoming connection.
683 //
684
685 FileDescriptor2 = EpollHandleClientAccept(FileDescriptor1);
686
687 LxtLogInfo("[Server] Writing to socket %d times!", WriteItemCount);
688
689 for (Index = 0; Index < WriteItemCount; Index += 1)
690 {
691
692 Result = write(FileDescriptor2, DataToWrite[Index], strlen(DataToWrite[Index]));
693
694 if (Result < 0)
695 {
696 LxtLogError("[Server] Write %d failed %d", Index, Result);
697
698 goto cleanup;
699 }
700
701 LxtLogInfo("[Server] Write (%d, %s, %d) -> %d!", FileDescriptor2, DataToWrite[Index], strlen(DataToWrite[Index]) + (Index == WriteItemCount - 1), Result);
702
703 if ((Index % 5) == 0)
704 {
705 usleep(5 * 1000 * 1000);
706 }
707 }
708
709 usleep(5 * 1000 * 1000);
710
711 LxtLogInfo("[Server] Closing client fd = %d", FileDescriptor2);
712 if (FileDescriptor2 != -1)
713 {
714 close(FileDescriptor2);
715 FileDescriptor2 = -1;
716 }
717
718 LxtLogInfo("[Server] Waiting for child to exit");
719
720 ChildStatus = 0;
721 wait(&ChildStatus);
722
723 LxtLogInfo("[Server] Child WIFEXITED=%d WEXITSTATUS=%d", WIFEXITED(ChildStatus), WEXITSTATUS(ChildStatus));
724
725 //
726 // Determine if the test passed or failed.
727 //
728
729 if ((Result < 0) || (WIFEXITED(ChildStatus) == 0) || (WEXITSTATUS(ChildStatus) != 0))
730 {
731
732 LxtLogInfo("[Server] Test failed!");
733 Result = -1;
734 }
735
736 LxtLogInfo("[Server] Done");
737
738 cleanup:
739
740 if (FileDescriptor1 != -1)
741 {
742 close(FileDescriptor1);
743 }
744
745 if (EpollFileDescriptor != -1)
746 {
747 close(EpollFileDescriptor);
748 }
749
750 if (FileDescriptor2 != -1)
751 {
752 close(FileDescriptor2);
753 }
754
755 if (ChildPid == 0)
756 {
757 LxtLogInfo("[Child] Exit with %d!", Result);
758 _exit(Result);
759 }
760
761 return Result;
762 }
763
764 int EpollHangupTestSimple(PLXT_ARGS Args)
765 {
766
767 char Buffer[256];
768 int Result;
769 int EpollFileDescriptor;
770 int FileDescriptor1;
771 int FileDescriptor2;
772 struct epoll_event EpollControlEvent;
773 struct epoll_event EpollWaitEvent[2];
774 int ChildPid;
775 int Index;
776 int ChildStatus;
777 int ReadAttempts;
778
779 //
780 // Initialize locals.
781 //
782
783 FileDescriptor1 = -1;
784 FileDescriptor2 = -1;
785 EpollFileDescriptor = -1;
786 ChildPid = -1;
787 LxtLogInfo("[Setup] Starting simple hangup test");
788
789 //
790 // Create the server socket.
791 //
792
793 LxtLogInfo("[Setup] About to create server socket");
794
795 FileDescriptor1 = EpollCreateListenSocket();
796 if (FileDescriptor1 == -1)
797 {
798 Result = errno;
799 LxtLogError("[Setup] Could not create server socket %d!", Result);
800 goto cleanup;
801 }
802
803 LxtLogInfo("[Setup] Created server socket successfully");
804
805 //
806 // Fork to create a server and a client.
807 //
808
809 LxtLogInfo("[Setup] About to fork");
810
811 ChildPid = fork();
812
813 if (ChildPid == -1)
814 {
815 Result = errno;
816 LxtLogError("[Setup] Fork failed! %d", Result);
817 goto cleanup;
818 }
819
820 if (ChildPid == 0)
821 {
822
823 LxtLogInfo("[Client] Connecting to server...");
824
825 FileDescriptor2 = EpollCreateClientSocket();
826
827 LxtLogInfo("[Client] Connected to server, fd = %d", FileDescriptor2);
828
829 LxtLogInfo("[Client] Sleeping for 3 seconds with open socket");
830
831 usleep(3 * 1000 * 1000);
832
833 //
834 // Create an epoll container.
835 //
836
837 EpollFileDescriptor = epoll_create(1);
838
839 if (EpollFileDescriptor == -1)
840 {
841 Result = errno;
842 LxtLogError("[Client] Could not create Epoll %d!", Result);
843 goto cleanup;
844 }
845
846 //
847 // Add the connected socket to the epoll.
848 //
849
850 EpollControlEvent.events = EPOLLIN;
851 EpollControlEvent.data.fd = FileDescriptor2;
852
853 Result = epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor2, &EpollControlEvent);
854
855 if (Result == -1)
856 {
857 Result = errno;
858 LxtLogError("[Client] Could not add file to epoll %d!", Result);
859 goto cleanup;
860 }
861
862 //
863 // Wait for data to be available with a timeout.
864 //
865
866 ReadAttempts = 0;
867 while (1)
868 {
869
870 LxtLogInfo("[Client] Waiting on epoll with 15 second timeout");
871
872 Result = epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 15000);
873
874 LxtLogInfo("[Client] Epoll returned %d events", Result);
875
876 if (Result == 0)
877 {
878 LxtLogError("[Client] No events returned, exiting!");
879 Result = -1;
880 goto cleanup;
881 }
882
883 if (Result != 1)
884 {
885 LxtLogError("[Client] Wait on epoll returned too many events, exiting!");
886 Result = -1;
887 goto cleanup;
888 }
889
890 LxtLogInfo("[Client] Event: {%d, %x} ", EpollWaitEvent[0].data.fd, EpollWaitEvent[0].events);
891
892 if (EpollWaitEvent[0].data.fd != FileDescriptor2)
893 {
894 LxtLogError("[Client] Epoll wait satisfied with wrong user data! %d", EpollWaitEvent[0].data.fd);
895 Result = -1;
896 goto cleanup;
897 }
898
899 if (EpollWaitEvent[0].events != EPOLLIN)
900 {
901 LxtLogError("[Client] Epoll wait satisfied with wrong events! 0x%x", EpollWaitEvent[0].events);
902 Result = -1;
903 goto cleanup;
904 }
905
906 memset(Buffer, 0, sizeof(Buffer));
907 Result = read(FileDescriptor2, Buffer, sizeof(Buffer));
908 if (Result < 0)
909 {
910 Result = errno;
911 LxtLogError("[Client] Read on socket failed! %d", Result);
912 goto cleanup;
913 }
914
915 LxtLogInfo("[Client] Read (%d) -> %d bytes: %s", FileDescriptor2, Result, Buffer);
916
917 if (Result == 0)
918 {
919 ReadAttempts += 1;
920 if (ReadAttempts < 2)
921 {
922 LxtLogInfo("[Client] Continuing even through read 0 bytes.");
923 continue;
924 }
925
926 LxtLogInfo("[Client] Exiting because read returned 0 bytes.");
927 goto cleanup;
928 }
929 }
930 }
931
932 //
933 // Accept an incoming connection.
934 //
935
936 LxtLogInfo("[Server] Waiting for incoming connections...");
937
938 FileDescriptor2 = EpollHandleClientAccept(FileDescriptor1);
939
940 LxtLogInfo("[Server] Connected to client, fd = %d", FileDescriptor2);
941
942 Result = write(FileDescriptor2, "Party On", strlen("Party On") + 1);
943
944 LxtLogInfo("[Server] Write (%d, %s, %d) -> %d", FileDescriptor2, "Party On", strlen("Party On") + 1, Result);
945
946 if (Result < 0)
947 {
948 LxtLogError("[Server] Write failed %s", strerror(errno));
949 goto cleanup;
950 }
951
952 LxtLogInfo("[Server] Closing client fd = %d", FileDescriptor2);
953 if (FileDescriptor2 != -1)
954 {
955 close(FileDescriptor2);
956 FileDescriptor2 = -1;
957 }
958
959 LxtLogInfo("[Server] Waiting for child to exit");
960
961 wait(&ChildStatus);
962
963 LxtLogInfo("[Server] Child WIFEXITED=%d WEXITSTATUS=%d", WIFEXITED(ChildStatus), WEXITSTATUS(ChildStatus));
964
965 //
966 // Determine if the test passed or failed.
967 //
968
969 if ((Result < 0) || (WIFEXITED(ChildStatus) == 0) || (WEXITSTATUS(ChildStatus) != 0))
970 {
971
972 LxtLogInfo("[Server] Test failed!");
973 Result = -1;
974 }
975
976 LxtLogInfo("[Server] Done");
977
978 cleanup:
979
980 if (FileDescriptor1 != -1)
981 {
982 close(FileDescriptor1);
983 }
984
985 if (EpollFileDescriptor != -1)
986 {
987 close(EpollFileDescriptor);
988 }
989
990 if (FileDescriptor2 != -1)
991 {
992 close(FileDescriptor2);
993 }
994
995 if (ChildPid == 0)
996 {
997 _exit(Result);
998 }
999
1000 return Result;
1001 }
1002
1003 int EpollSocketAcceptTest(PLXT_ARGS Args)
1004
1005 /*++
1006 --*/
1007
1008 {
1009
1010 char Buffer[256];
1011 int Result;
1012 int EpollFileDescriptor;
1013 int FileDescriptor1;
1014 int FileDescriptor2;
1015 struct epoll_event EpollControlEvent;
1016 struct epoll_event EpollWaitEvent[2];
1017 int ChildPid;
1018 int Index;
1019 int ChildStatus;
1020
1021 //
1022 // Initialize locals.
1023 //
1024
1025 FileDescriptor1 = -1;
1026 FileDescriptor2 = -1;
1027 EpollFileDescriptor = -1;
1028 ChildPid = -1;
1029
1030 //
1031 // Create a socket that will be added for epoll.
1032 //
1033
1034 FileDescriptor1 = EpollCreateListenSocket();
1035 if (FileDescriptor1 == -1)
1036 {
1037 Result = errno;
1038 LxtLogError("Could not create socket! %d", Result);
1039 goto cleanup;
1040 }
1041
1042 //
1043 // Create an epoll container.
1044 //
1045
1046 EpollFileDescriptor = epoll_create(1);
1047
1048 if (EpollFileDescriptor == -1)
1049 {
1050 Result = errno;
1051 LxtLogError("Could not create Epoll! %d", Result);
1052 goto cleanup;
1053 }
1054
1055 //
1056 // Add the socket to the epoll.
1057 //
1058
1059 EpollControlEvent.events = EPOLLIN;
1060 EpollControlEvent.data.fd = FileDescriptor1;
1061
1062 Result = epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor1, &EpollControlEvent);
1063
1064 if (Result == -1)
1065 {
1066 Result = errno;
1067 LxtLogError("Could not add file to epoll! %d", Result);
1068 goto cleanup;
1069 }
1070
1071 //
1072 // Wait for data to be available with a timeout. No data should arrive.
1073 //
1074
1075 LxtLogInfo("[Setup] Waiting on epoll to timeout for 5s...");
1076
1077 Result = epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 5000);
1078
1079 if (Result == -1)
1080 {
1081 Result = errno;
1082 LxtLogError("Waiting on epoll failed! %d", Result);
1083 goto cleanup;
1084 }
1085
1086 if (Result != 0)
1087 {
1088 LxtLogError("Waiting on epoll succeeded but returned non-zero events! %d", Result);
1089 Result = -1;
1090 goto cleanup;
1091 }
1092
1093 LxtLogInfo("[Setup] Wait on epoll returned no data, as expected...");
1094
1095 //
1096 // Fork to create a server and a client.
1097 //
1098
1099 LxtLogInfo("[Setup] About to fork...");
1100
1101 ChildPid = fork();
1102
1103 if (ChildPid == -1)
1104 {
1105 Result = errno;
1106 LxtLogError("Fork failed! %d", Result);
1107 goto cleanup;
1108 }
1109
1110 if (ChildPid == 0)
1111 {
1112
1113 LxtLogInfo("[Client] Waiting 2 seconds to let server block...");
1114
1115 usleep(2 * 1000 * 1000);
1116
1117 LxtLogInfo("[Client] Connecting to server...");
1118
1119 FileDescriptor2 = EpollCreateClientSocket();
1120
1121 LxtLogInfo("[Client] Connected to server, fd =%d", FileDescriptor2);
1122
1123 LxtLogInfo("[Client] Sleeping for 2 seconds with open socket");
1124
1125 usleep(2 * 1000 * 1000);
1126
1127 Result = write(FileDescriptor2, "Party On", strlen("Party On") + 1);
1128
1129 LxtLogInfo("[Client] Write (%d, %s, %d) -> %d", FileDescriptor2, "Party On", strlen("Party On") + 1, Result);
1130
1131 if (Result < 0)
1132 {
1133 LxtLogError("[Server] Write failed %s", strerror(errno));
1134 goto cleanup;
1135 }
1136
1137 LxtLogInfo("[Client] Closing socket %d", FileDescriptor2);
1138
1139 if (close(FileDescriptor2) != 0)
1140 {
1141 LxtLogError("[Client] Closing socket %d failed - %s", FileDescriptor2, strerror(errno));
1142 }
1143
1144 usleep(2 * 1000 * 1000);
1145
1146 FileDescriptor2 = -1;
1147 goto cleanup;
1148 }
1149
1150 //
1151 // The server should wait for data to become available on the socket.
1152 //
1153
1154 LxtLogInfo("[Server] Waiting on epoll to timeout for 10s...");
1155
1156 Result = epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 10000);
1157
1158 if (Result == -1)
1159 {
1160 Result = errno;
1161 LxtLogError("[Server] Waiting on epoll failed! %d", Result);
1162 goto cleanup;
1163 }
1164
1165 if (Result != 1)
1166 {
1167 LxtLogError("[Server] Waiting on epoll returned unexpected events: %d!", Result);
1168 Result = -1;
1169 goto cleanup;
1170 }
1171
1172 if (EpollWaitEvent[0].data.fd != FileDescriptor1)
1173 {
1174 LxtLogError("[Server] Epoll wait satisfied with wrong user data! %d", EpollWaitEvent[0].data.fd);
1175 Result = -1;
1176 goto cleanup;
1177 }
1178
1179 if (EpollWaitEvent[0].events != EPOLLIN)
1180 {
1181 LxtLogError("[Server] Epoll wait satisfied with wrong events! 0x%x", EpollWaitEvent[0].events);
1182 Result = -1;
1183 goto cleanup;
1184 }
1185
1186 FileDescriptor2 = EpollHandleClientAccept(FileDescriptor1);
1187 if (FileDescriptor2 < 0)
1188 {
1189 LxtLogError("[Server] Accept failed!");
1190 Result = -1;
1191 }
1192
1193 LxtLogInfo("[Server] Accepted a request successfully...");
1194
1195 //
1196 // The server should timeout now if it waits for data again.
1197 //
1198
1199 LxtLogInfo("[Server] Waiting on epoll to timeout for 5s...");
1200
1201 Result = epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 5000);
1202
1203 if (Result == -1)
1204 {
1205 Result = errno;
1206 LxtLogError("Waiting on epoll failed! %d", Result);
1207 goto cleanup;
1208 }
1209
1210 if (Result != 0)
1211 {
1212 LxtLogError("Waiting on epoll succeeded but returned non-zero events! %d", Result);
1213 Result = -1;
1214 goto cleanup;
1215 }
1216
1217 //
1218 // Add the socket to the epoll.
1219 //
1220
1221 EpollControlEvent.events = EPOLLIN;
1222 EpollControlEvent.data.fd = FileDescriptor2;
1223
1224 Result = epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor2, &EpollControlEvent);
1225
1226 if (Result == -1)
1227 {
1228 Result = errno;
1229 LxtLogError("Could not add file to epoll! %d", Result);
1230 goto cleanup;
1231 }
1232
1233 //
1234 // Wait for data to be available with a timeout. No data should arrive.
1235 //
1236
1237 while (1)
1238 {
1239
1240 LxtLogInfo("[Setup] Waiting on epoll to timeout for 5s...");
1241
1242 Result = epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 5000);
1243
1244 if (Result == -1)
1245 {
1246 Result = errno;
1247 LxtLogError("Waiting on epoll failed! %d", Result);
1248 goto cleanup;
1249 }
1250
1251 if (Result == 0)
1252 {
1253 LxtLogError("Waiting on epoll succeeded but returned zero events!");
1254 Result = -1;
1255 goto cleanup;
1256 }
1257
1258 LxtLogInfo("[Server] Event: {%d, %x} ", EpollWaitEvent[0].data.fd, EpollWaitEvent[0].events);
1259
1260 if (EpollWaitEvent[0].data.fd != FileDescriptor2)
1261 {
1262 LxtLogError("[Server] Epoll wait satisfied with wrong user data! %d", EpollWaitEvent[0].data.fd);
1263 Result = -1;
1264 goto cleanup;
1265 }
1266
1267 if (EpollWaitEvent[0].events != EPOLLIN)
1268 {
1269 LxtLogError("[Server] Epoll wait satisfied with wrong events! 0x%x", EpollWaitEvent[0].events);
1270 Result = -1;
1271 goto cleanup;
1272 }
1273
1274 memset(Buffer, 0, sizeof(Buffer));
1275 Result = read(FileDescriptor2, Buffer, sizeof(Buffer));
1276 if (Result < 0)
1277 {
1278 Result = errno;
1279 LxtLogError("[Client] Read on socket failed! %d", Result);
1280 goto cleanup;
1281 }
1282
1283 LxtLogInfo("[Server] read %d bytes: %s ...", Result, Buffer);
1284
1285 if (Result == 0)
1286 {
1287 LxtLogInfo("[Server] exiting ...");
1288 goto cleanup;
1289 }
1290 }
1291
1292 LxtLogInfo("[Server] Waiting on child");
1293
1294 wait(&ChildStatus);
1295
1296 LxtLogInfo("[Server] Child WIFEXITED=%d WEXITSTATUS=%d", WIFEXITED(ChildStatus), WEXITSTATUS(ChildStatus));
1297
1298 //
1299 // Determine if the test passed or failed.
1300 //
1301
1302 if ((Result < 0) || (WIFEXITED(ChildStatus) == 0) || (WEXITSTATUS(ChildStatus) != 0))
1303 {
1304
1305 LxtLogInfo("[Server] Test failed!");
1306 Result = -1;
1307 }
1308
1309 LxtLogInfo("[Server] Done");
1310
1311 cleanup:
1312
1313 if (FileDescriptor1 != -1)
1314 {
1315 close(FileDescriptor1);
1316 }
1317
1318 if (EpollFileDescriptor != -1)
1319 {
1320 close(EpollFileDescriptor);
1321 }
1322
1323 if (FileDescriptor2 != -1)
1324 {
1325 close(FileDescriptor2);
1326 }
1327
1328 if (ChildPid == 0)
1329 {
1330 _exit(Result);
1331 }
1332
1333 return Result;
1334 }
1335
1336 int EpollVariation0(PLXT_ARGS Args)
1337
1338 /*++
1339 --*/
1340
1341 {
1342
1343 char Buffer[10];
1344 int BytesReadWrite;
1345 int ChildPid;
1346 struct epoll_event EpollControlEvent;
1347 int FileDescriptor1;
1348 int FileDescriptor2;
1349 int EpollFileDescriptor;
1350 struct epoll_event EpollWaitEvent[2];
1351 int Index;
1352 int Master;
1353 char PtsDevName[50];
1354 int Result;
1355 int Status;
1356
1357 //
1358 // Initialize locals.
1359 //
1360
1361 Master = -1;
1362 FileDescriptor1 = -1;
1363 FileDescriptor2 = -1;
1364 EpollFileDescriptor = -1;
1365 ChildPid = -1;
1366
1367 //
1368 // Open a file that will be added to the epoll.
1369 //
1370
1371 LxtCheckErrno(Master = open("/dev/ptmx", O_RDWR));
1372 LxtCheckErrno(grantpt(Master));
1373 LxtCheckErrno(unlockpt(Master));
1374 LxtCheckErrno(ptsname_r(Master, PtsDevName, sizeof(PtsDevName)));
1375 LxtLogInfo("Subordinate Device is:%s", PtsDevName);
1376 LxtCheckErrno(FileDescriptor1 = open(PtsDevName, O_RDWR));
1377 LxtCheckErrno(FileDescriptor2 = open(PtsDevName, O_RDWR));
1378
1379 //
1380 // Create an epoll.
1381 //
1382
1383 LxtCheckErrno(EpollFileDescriptor = epoll_create(1));
1384
1385 //
1386 // Add the file to the epoll.
1387 //
1388
1389 EpollControlEvent.events = EPOLLIN;
1390 EpollControlEvent.data.fd = FileDescriptor1;
1391 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor1, &EpollControlEvent));
1392
1393 //
1394 // Add the file to the epoll again and it should fail.
1395 //
1396
1397 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor1, &EpollControlEvent), EEXIST);
1398
1399 //
1400 // Add the epoll file descriptor to itself and it should fail.
1401 //
1402
1403 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, EpollFileDescriptor, &EpollControlEvent), EINVAL);
1404
1405 //
1406 // Add the second file descriptor to the epoll.
1407 //
1408
1409 EpollControlEvent.events = EPOLLOUT | EPOLLPRI;
1410 EpollControlEvent.data.fd = FileDescriptor2;
1411 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor2, &EpollControlEvent));
1412
1413 //
1414 // Remove the second file from the epoll.
1415 //
1416
1417 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_DEL, FileDescriptor2, NULL));
1418
1419 //
1420 // Try adding back the first file descriptor as it should still be there.
1421 //
1422
1423 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor1, &EpollControlEvent), EEXIST);
1424
1425 //
1426 // Add the second file descriptor back to the epoll.
1427 //
1428
1429 EpollControlEvent.events = EPOLLOUT | EPOLLPRI;
1430 EpollControlEvent.data.fd = FileDescriptor2;
1431 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, FileDescriptor2, &EpollControlEvent));
1432
1433 //
1434 // Modify the second file descriptor in the epoll.
1435 //
1436
1437 EpollControlEvent.events = EPOLLIN | EPOLLERR | EPOLLPRI | EPOLLET;
1438 EpollControlEvent.data.fd = FileDescriptor2;
1439 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_MOD, FileDescriptor2, &EpollControlEvent));
1440
1441 //
1442 // Wait for the epoll with a timeout.
1443 //
1444
1445 LxtLogInfo("Waiting on epoll to timeout for 1s...");
1446
1447 LxtCheckErrnoZeroSuccess(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 200));
1448
1449 //
1450 // Fork to create another thread to signal the epoll.
1451 //
1452
1453 LXT_SYNCHRONIZATION_POINT_START();
1454 LxtCheckErrno(ChildPid = fork());
1455 if (ChildPid == 0)
1456 {
1457
1458 //
1459 // Wait to allow parent to block on epoll.
1460 //
1461
1462 LXT_SYNCHRONIZATION_POINT();
1463 LxtLogInfo("T2: Waiting to make read data available...");
1464 usleep(200 * 1000);
1465 LxtLogInfo("T2: Making data available for read...");
1466 LxtCheckErrno((BytesReadWrite = write(Master, "\n", 1)));
1467
1468 LXT_SYNCHRONIZATION_POINT();
1469 usleep(200 * 1000);
1470 LxtLogInfo("T2: Making data available for read...");
1471 LxtCheckErrno(BytesReadWrite = read(FileDescriptor1, Buffer, sizeof(Buffer)));
1472 LxtCheckEqual(BytesReadWrite, 1, "%d");
1473 LxtCheckErrno((BytesReadWrite = write(Master, "\n", 1)));
1474
1475 LxtLogInfo("T2: Waiting to allow T1 to wake, consume edge trigger, and wait again...");
1476 LXT_SYNCHRONIZATION_POINT();
1477 usleep(200 * 1000);
1478 LxtLogInfo("T2: Clearing edge-trigger on descriptor2...");
1479 LxtCheckErrno(BytesReadWrite = read(FileDescriptor1, Buffer, sizeof(Buffer)));
1480 LxtCheckEqual(BytesReadWrite, 1, "%d");
1481 LXT_SYNCHRONIZATION_POINT();
1482
1483 LXT_SYNCHRONIZATION_POINT();
1484 LxtLogInfo("T2: Making data available for read...");
1485 LxtCheckErrno((BytesReadWrite = write(Master, "\n", 1)));
1486
1487 Result = LXT_RESULT_SUCCESS;
1488 goto ErrorExit;
1489 }
1490
1491 //
1492 // Wait on epoll to be woken by the child. Do this twice and the second time
1493 // should immediately return since the first epoll is still signalled.
1494 //
1495
1496 for (Index = 0; Index < 2; Index += 1)
1497 {
1498
1499 LxtLogInfo("T1: Waiting for epoll to be signaled for first descriptor...");
1500 LXT_SYNCHRONIZATION_POINT();
1501 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, -1));
1502 LxtCheckEqual(Result, (2 - Index), "%d");
1503 if (EpollWaitEvent[0].data.fd == FileDescriptor1)
1504 {
1505 LxtCheckEqual(EpollWaitEvent[0].data.fd, FileDescriptor1, "%d");
1506 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "%d");
1507 if (Result > 1)
1508 {
1509 LxtCheckEqual(EpollWaitEvent[1].data.fd, FileDescriptor2, "%d");
1510 LxtCheckEqual(EpollWaitEvent[1].events, EPOLLIN, "%d");
1511 }
1512 }
1513 else
1514 {
1515 LxtCheckEqual(EpollWaitEvent[0].data.fd, FileDescriptor2, "%d");
1516 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "%d");
1517 if (Result > 1)
1518 {
1519 LxtCheckEqual(EpollWaitEvent[1].data.fd, FileDescriptor1, "%d");
1520 LxtCheckEqual(EpollWaitEvent[1].events, EPOLLIN, "%d");
1521 }
1522 }
1523
1524 // LxtCheckErrno(BytesReadWrite = read(FileDescriptor1, Buffer, sizeof(Buffer)));
1525 // LxtCheckEqual(BytesReadWrite, 1, "%d");
1526 if (Index == 0)
1527 {
1528
1529 //
1530 // Modify the first file descriptor in the epoll to be one shot. This
1531 // way, when it's waited on again in the next iteration of the loop,
1532 // it will be disabled.
1533 //
1534
1535 EpollControlEvent.events = EPOLLIN | EPOLLONESHOT;
1536 EpollControlEvent.data.fd = FileDescriptor1;
1537 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_MOD, FileDescriptor1, &EpollControlEvent));
1538 }
1539 }
1540
1541 //
1542 // Now wait for the epoll to be signalled by the child for the second
1543 // descriptor. That registration was with an edge trigger.
1544 //
1545
1546 LXT_SYNCHRONIZATION_POINT();
1547 LxtLogInfo("T1: Waiting for epoll to be signaled for second descriptor...");
1548 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, -1));
1549 LxtCheckEqual(Result, 1, "%d");
1550 LxtCheckEqual(EpollWaitEvent[0].data.fd, FileDescriptor2, "%d");
1551 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "%d");
1552
1553 //
1554 // Wait for the epoll again and it should timeout this time due to edge
1555 // trigger.
1556 //
1557
1558 LXT_SYNCHRONIZATION_POINT();
1559 LxtLogInfo("Waiting on epoll to timeout...");
1560 LxtCheckErrnoZeroSuccess(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 200));
1561
1562 //
1563 // Signal the event again, but descriptor 1 is marked oneshot so it still
1564 // won't deliver any notifications.
1565 //
1566
1567 LXT_SYNCHRONIZATION_POINT();
1568 LxtLogInfo("Waiting on epoll (T1 to ready data) indefinitely...");
1569 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, -1));
1570 LxtCheckEqual(Result, 1, "%d");
1571 LxtCheckEqual(EpollWaitEvent[0].data.fd, FileDescriptor2, "%d");
1572 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "%d");
1573
1574 //
1575 // Making data unavailable for both descriptors. And generating error on
1576 // second descriptor.
1577 //
1578
1579 LxtCheckClose(Master);
1580 LxtLogInfo("Waiting on epoll for error indefinitely...");
1581 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, -1));
1582 LxtCheckEqual(Result, 1, "%d");
1583 LxtCheckEqual(EpollWaitEvent[0].data.fd, FileDescriptor2, "%d");
1584
1585 //
1586 // TODO_LX: Currently only signalling EPOLLHUP.
1587 //
1588 // LxtCheckEqual(EpollWaitEvent[0].events, (EPOLLHUP | EPOLLERR | EPOLLIN), "%d");
1589 //
1590
1591 Result = LXT_RESULT_SUCCESS;
1592
1593 ErrorExit:
1594
1595 //
1596 // Close the file descriptors in a specific order to exercise both code
1597 // paths where a file is closed while in an epoll and epoll is closed while
1598 // having files in it.
1599 //
1600
1601 if (FileDescriptor2 != -1)
1602 {
1603 close(FileDescriptor2);
1604 }
1605
1606 if (EpollFileDescriptor != -1)
1607 {
1608 close(EpollFileDescriptor);
1609 }
1610
1611 if (FileDescriptor1 != -1)
1612 {
1613 close(FileDescriptor1);
1614 }
1615
1616 if (Master != -1)
1617 {
1618 close(Master);
1619 }
1620
1621 LXT_SYNCHRONIZATION_POINT_END();
1622 return Result;
1623 }
1624
1625 typedef struct _READD_TEST_DATA
1626 {
1627 int Fd;
1628 int EpollFd;
1629 } READD_TEST_DATA, *PREADD_TEST_DATA;
1630
1631 static READD_TEST_DATA ReAddTestData;
1632
1633 static int EpollReAddTestClone(void* Parameter)
1634
1635 /*++
1636 --*/
1637
1638 {
1639
1640 struct epoll_event EpollControlEvent;
1641 int Result = -1;
1642
1643 //
1644 // Try to close file descriptor already added to epoll.
1645 //
1646
1647 EpollControlEvent.events = EPOLLIN | EPOLLET;
1648 EpollControlEvent.data.fd = ReAddTestData.Fd;
1649 LxtLogInfo("[Cloned] Trying to add existing fd (%d) to epoll context", ReAddTestData.Fd);
1650
1651 LxtCheckErrnoFailure(epoll_ctl(ReAddTestData.EpollFd, EPOLL_CTL_ADD, ReAddTestData.Fd, &EpollControlEvent), EEXIST);
1652
1653 LxtLogInfo("[Cloned] Closing fd (%d) in shared file descriptor table", ReAddTestData.Fd);
1654
1655 LxtClose(ReAddTestData.Fd);
1656 Result = 0;
1657
1658 ErrorExit:
1659 LxtLogInfo("[Cloned] Exiting...");
1660 exit(Result);
1661 }
1662
1663 int EpollAddTest(PLXT_ARGS Args)
1664
1665 /*++
1666 --*/
1667
1668 {
1669 int Result;
1670 int ChildPid;
1671 struct epoll_event EpollControlEvent;
1672 int EpollFd;
1673 int SocketFd1;
1674 int SocketFdCopy;
1675 int SocketFd2;
1676 int SocketFd3;
1677 int SocketFd4;
1678 int Status;
1679 LXT_CLONE_ARGS CloneArgs;
1680
1681 SocketFd1 = -1;
1682 SocketFd2 = -1;
1683 SocketFd3 = -1;
1684 EpollFd = -1;
1685 int Flags;
1686
1687 LxtCheckErrno(EpollFd = epoll_create1(EPOLL_CLOEXEC));
1688 LxtCheckErrno(SocketFd1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
1689 LxtCheckErrno(SocketFd3 = dup(SocketFd1));
1690 LxtLogInfo("Created fd1 (%d), duplicated into fd3 (%d)", SocketFd1, SocketFd3);
1691 EpollControlEvent.events = EPOLLIN | EPOLLET;
1692 EpollControlEvent.data.fd = SocketFd1;
1693 LxtLogInfo("Adding fd1 (%d) file descriptor to epoll context", SocketFd1);
1694 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd1, &EpollControlEvent));
1695
1696 LxtLogInfo("Adding fd3 (%d) file descriptor to epoll context", SocketFd3);
1697 EpollControlEvent.data.fd = SocketFd3;
1698 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd3, &EpollControlEvent));
1699
1700 LxtLogInfo("Closing fd1 (%d) file descriptor", SocketFd1);
1701 LxtClose(SocketFd1);
1702 SocketFdCopy = SocketFd1;
1703 SocketFd1 = -1;
1704 LxtCheckErrno(SocketFd2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
1705 LxtLogInfo("Created fd2 (%d) file descriptor, that should be the same as closed fd1 (%d)", SocketFd2, SocketFdCopy);
1706
1707 LxtCheckEqual(SocketFdCopy, SocketFd2, "%d");
1708 LxtCheckNotEqual(SocketFd1, SocketFd3, "%d");
1709 EpollControlEvent.data.fd = SocketFd2;
1710 LxtLogInfo("Adding fd2 (%d) file descriptor to epoll context", SocketFd2);
1711 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd2, &EpollControlEvent));
1712
1713 LxtLogInfo("Trying to add fd3 (%d) file descriptor, expecting EEXIST", SocketFd3);
1714 EpollControlEvent.data.fd = SocketFd3;
1715 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd3, &EpollControlEvent), EEXIST);
1716
1717 LxtLogInfo("Forking...");
1718 LXT_SYNCHRONIZATION_POINT_START();
1719 LxtCheckErrno(ChildPid = fork());
1720 if (ChildPid == 0)
1721 {
1722 LXT_SYNCHRONIZATION_POINT();
1723
1724 LxtLogInfo("[Forked] Try to add fd3 (%d) already added to epoll context", SocketFd3);
1725 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd3, &EpollControlEvent), EEXIST);
1726
1727 LxtLogInfo("[Forked] Closing fd3 (%d), should not affect parent", SocketFd3);
1728 LxtClose(SocketFd3);
1729 SocketFd3 = -1;
1730 LXT_SYNCHRONIZATION_POINT();
1731
1732 //
1733 // Let the parent try to add already existing file descriptor, verifying
1734 // that it hasn't been removed in both file descriptor tables.
1735 //
1736
1737 LXT_SYNCHRONIZATION_POINT();
1738
1739 LxtCheckErrno(SocketFd3 = dup(SocketFd2));
1740 LxtLogInfo("[Forked] Duplicated fd2 (%d) to fd3 (%d) and adding fd3 to epoll context", SocketFd2, SocketFd3);
1741 EpollControlEvent.data.fd = SocketFd3;
1742 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd3, &EpollControlEvent));
1743
1744 goto ErrorExit;
1745 }
1746
1747 LXT_SYNCHRONIZATION_POINT();
1748
1749 //
1750 // Let the child process close the file descriptor in the cloned file
1751 // descriptor table.
1752 //
1753
1754 LXT_SYNCHRONIZATION_POINT();
1755
1756 LxtLogInfo("Try to add fd3 (%d) already added to epoll context", SocketFd3);
1757 EpollControlEvent.data.fd = SocketFd3;
1758 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd3, &EpollControlEvent), EEXIST);
1759
1760 LXT_SYNCHRONIZATION_POINT();
1761
1762 ErrorExit:
1763 if (SocketFd1 != -1)
1764 {
1765 close(SocketFd1);
1766 }
1767
1768 if (SocketFd2 != -1)
1769 {
1770 close(SocketFd2);
1771 }
1772
1773 if (SocketFd3 != -1)
1774 {
1775 close(SocketFd3);
1776 }
1777
1778 if (EpollFd != -1)
1779 {
1780 close(EpollFd);
1781 }
1782
1783 LXT_SYNCHRONIZATION_POINT_END();
1784 return Result;
1785 }
1786
1787 int EpollDeleteTest(PLXT_ARGS Args)
1788
1789 /*++
1790 --*/
1791
1792 {
1793 int Result;
1794 int ChildPid;
1795 struct epoll_event EpollControlEvent;
1796 int EpollFd;
1797 int SocketFd;
1798 int SocketFdCopy;
1799 int SocketFdDup;
1800 int Status;
1801 LXT_CLONE_ARGS CloneArgs;
1802
1803 SocketFd = -1;
1804 EpollFd = -1;
1805 int Flags;
1806
1807 LxtCheckErrno(EpollFd = epoll_create1(EPOLL_CLOEXEC));
1808 LxtCheckErrno(SocketFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
1809 LxtLogInfo("Created socket file descriptor (%d)", SocketFd);
1810 EpollControlEvent.events = EPOLLIN | EPOLLET;
1811 EpollControlEvent.data.fd = SocketFd;
1812 LxtLogInfo("Adding socket file descriptor (%d) to epoll context", SocketFd);
1813 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent));
1814
1815 LxtLogInfo("1. Forking...");
1816 LXT_SYNCHRONIZATION_POINT_START();
1817 LxtCheckErrno(ChildPid = fork());
1818 if (ChildPid == 0)
1819 {
1820 LxtLogInfo("[Forked] Try to add socket file descriptor (%d) already added to epoll context", SocketFd);
1821 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent), EEXIST);
1822
1823 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_DEL, SocketFd, NULL));
1824
1825 LXT_SYNCHRONIZATION_POINT();
1826
1827 //
1828 // Let the parent re-add socket file descriptor.
1829 //
1830
1831 LXT_SYNCHRONIZATION_POINT();
1832 goto ErrorExit;
1833 }
1834
1835 //
1836 // Let the child process remove the file descriptor in the cloned file
1837 // descriptor table.
1838 //
1839
1840 LXT_SYNCHRONIZATION_POINT();
1841 LxtLogInfo("Try to add socket file descriptor (%d)", SocketFd);
1842 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent));
1843
1844 LXT_SYNCHRONIZATION_POINT();
1845 LXT_SYNCHRONIZATION_POINT_END();
1846 ChildPid = -1;
1847 LxtCheckResult(Result);
1848
1849 LxtLogInfo("2. Forking...");
1850 LxtCheckErrno(ChildPid = fork());
1851 if (ChildPid == 0)
1852 {
1853 LxtLogInfo("[Forked] Closing original socket fd and creating a new socket fd, should be equal");
1854 SocketFdCopy = SocketFd;
1855 LxtClose(SocketFd);
1856 LxtCheckErrno(SocketFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
1857 LxtCheckEqual(SocketFd, SocketFdCopy, "%d");
1858 LxtLogInfo("[Forked] Trying to delete socket file descriptor (%d), should fail", SocketFd);
1859 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_DEL, SocketFd, NULL), ENOENT);
1860
1861 LxtLogInfo("[Forked] Try to add socket file descriptor (%d)", SocketFd);
1862 EpollControlEvent.data.fd = SocketFd;
1863 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent));
1864
1865 LXT_SYNCHRONIZATION_POINT();
1866
1867 //
1868 // Let parent run.
1869 //
1870
1871 LXT_SYNCHRONIZATION_POINT();
1872
1873 LxtLogInfo("[Forked] Trying to delete socket file descriptor (%d) again", SocketFd);
1874 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_DEL, SocketFd, NULL));
1875
1876 LXT_SYNCHRONIZATION_POINT();
1877
1878 //
1879 // Let the parent re-add socket file descriptor.
1880 //
1881
1882 LXT_SYNCHRONIZATION_POINT();
1883 goto ErrorExit;
1884 }
1885
1886 //
1887 // Let the child process remove the file descriptor in the cloned file
1888 // descriptor table.
1889 //
1890
1891 LXT_SYNCHRONIZATION_POINT();
1892
1893 LxtLogInfo("Try to add socket file descriptor (%d), should fail", SocketFd);
1894 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent), EEXIST);
1895
1896 LXT_SYNCHRONIZATION_POINT();
1897
1898 //
1899 // Let child run.
1900 //
1901
1902 LXT_SYNCHRONIZATION_POINT();
1903
1904 LxtLogInfo("Try to add socket file descriptor (%d), should fail again", SocketFd);
1905 LxtCheckErrnoFailure(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent), EEXIST);
1906
1907 LXT_SYNCHRONIZATION_POINT();
1908 LXT_SYNCHRONIZATION_POINT_END();
1909 ChildPid = -1;
1910 LxtCheckResult(Result);
1911
1912 LxtLogInfo("3.Forking...");
1913 LxtCheckErrno(ChildPid = fork());
1914 if (ChildPid == 0)
1915 {
1916 LxtLogInfo("[Forked] Duplicating original socket fd and creating a new socket fd, should be equal");
1917 LxtCheckErrno(SocketFdDup = dup(SocketFd));
1918 LxtLogInfo("[Forked] Closing original socket fd and creating a new socket fd, should be equal");
1919 SocketFdCopy = SocketFd;
1920 LxtClose(SocketFd);
1921 LxtLogInfo("[Forked] Duplicating original socket fd into new socket fd, should be equal as the closed socket fd");
1922 LxtCheckErrno(SocketFd = dup(SocketFdDup));
1923 LxtCheckEqual(SocketFd, SocketFdCopy, "%d");
1924 LxtLogInfo("[Forked] Trying to delete socket file descriptor (%d)", SocketFd);
1925 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_DEL, SocketFd, NULL));
1926
1927 LXT_SYNCHRONIZATION_POINT();
1928
1929 //
1930 // Let the parent run.
1931 //
1932
1933 LXT_SYNCHRONIZATION_POINT();
1934 goto ErrorExit;
1935 }
1936
1937 //
1938 // Let the child process remove the file descriptor in the cloned file
1939 // descriptor table.
1940 //
1941
1942 LXT_SYNCHRONIZATION_POINT();
1943
1944 LxtLogInfo("Try to add socket file descriptor (%d)", SocketFd);
1945 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketFd, &EpollControlEvent));
1946
1947 LXT_SYNCHRONIZATION_POINT();
1948
1949 //
1950 // Let the child process finish.
1951 //
1952
1953 ErrorExit:
1954 if (SocketFd != -1)
1955 {
1956 close(SocketFd);
1957 }
1958
1959 if (EpollFd != -1)
1960 {
1961 close(EpollFd);
1962 }
1963
1964 LXT_SYNCHRONIZATION_POINT_END();
1965 return Result;
1966 }
1967
1968 int EpollModifyWhilePollingTest(PLXT_ARGS Args)
1969
1970 /*++
1971 --*/
1972
1973 {
1974
1975 int ChildPid;
1976 struct epoll_event EpollControlEvent;
1977 int EpollFileDescriptor;
1978 struct epoll_event EpollWaitEvent[2];
1979 struct epoll_event* InputEvent;
1980 struct epoll_event* OutputEvent;
1981 int PipeFileDescriptors[2] = {-1, -1};
1982 int Result;
1983 int Status;
1984
1985 //
1986 // Initialize locals.
1987 //
1988
1989 ChildPid = -1;
1990 EpollFileDescriptor = -1;
1991
1992 LxtCheckResult(LxtSignalInitialize());
1993 LxtCheckResult(LxtSignalSetupHandler(SIGPIPE, SA_SIGINFO));
1994
1995 //
1996 // Open a pipe to test epoll.
1997 //
1998
1999 LxtCheckErrnoZeroSuccess(pipe(PipeFileDescriptors));
2000
2001 //
2002 // Create an epoll.
2003 //
2004
2005 LxtCheckErrno(EpollFileDescriptor = epoll_create(1));
2006
2007 //
2008 // Add the file to the epoll.
2009 //
2010
2011 LXT_SYNCHRONIZATION_POINT_START();
2012 LxtCheckErrno(ChildPid = fork());
2013 if (ChildPid == 0)
2014 {
2015 LxtCheckClose(PipeFileDescriptors[0]);
2016 LxtCheckClose(PipeFileDescriptors[1]);
2017 LXT_SYNCHRONIZATION_POINT();
2018 LxtLogInfo("Waiting on epoll...", Result);
2019 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 2000));
2020 LxtCheckEqual(Result, 1, "%d");
2021 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLOUT, "%d");
2022 LxtCheckEqual(EpollWaitEvent[0].data.fd, 0, "%d");
2023 LXT_SYNCHRONIZATION_POINT();
2024 LXT_SYNCHRONIZATION_POINT();
2025 LxtLogInfo("Waiting on epoll...", Result);
2026 LxtCheckErrnoZeroSuccess(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 2000));
2027 goto ErrorExit;
2028 }
2029
2030 LXT_SYNCHRONIZATION_POINT();
2031 sleep(1);
2032 EpollControlEvent.events = EPOLLIN;
2033 EpollControlEvent.data.fd = 0;
2034 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, 0, &EpollControlEvent));
2035
2036 EpollControlEvent.events = EPOLLIN;
2037 EpollControlEvent.data.fd = PipeFileDescriptors[0];
2038 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
2039
2040 EpollControlEvent.events = EPOLLOUT | EPOLLONESHOT;
2041 EpollControlEvent.data.fd = 0;
2042 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_MOD, 0, &EpollControlEvent));
2043
2044 LXT_SYNCHRONIZATION_POINT();
2045
2046 //
2047 // The child consumed the epoll event so it should no longer be available.
2048 //
2049
2050 LxtCheckErrno(epoll_wait(EpollFileDescriptor, EpollWaitEvent, 2, 0));
2051 LxtCheckEqual(Result, 0, "%d");
2052
2053 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_DEL, 0, NULL));
2054
2055 LXT_SYNCHRONIZATION_POINT();
2056 sleep(1);
2057 LxtLogInfo("Closing last file descriptor in epoll.", Result);
2058 LxtCheckClose(PipeFileDescriptors[0]);
2059
2060 //
2061 // The epoll is active, but the pipe it was waiting on is now closed.
2062 //
2063
2064 LxtCheckErrnoFailure(write(PipeFileDescriptors[1], "\n", 1), EPIPE);
2065 LxtCheckResult(LxtSignalCheckReceived(SIGPIPE));
2066 LxtSignalResetReceived();
2067 LxtCheckClose(PipeFileDescriptors[1]);
2068
2069 ErrorExit:
2070 if (EpollFileDescriptor != -1)
2071 {
2072 close(EpollFileDescriptor);
2073 }
2074
2075 if (PipeFileDescriptors[1] != -1)
2076 {
2077 close(PipeFileDescriptors[1]);
2078 }
2079
2080 if (PipeFileDescriptors[0] != -1)
2081 {
2082 close(PipeFileDescriptors[0]);
2083 }
2084
2085 LxtLogInfo("Done, PID=%d, ChildPid=%d", getpid(), ChildPid);
2086 LXT_SYNCHRONIZATION_POINT_END();
2087 return Result;
2088 }
2089
2090 int EpollModTest(PLXT_ARGS Args)
2091
2092 /*++
2093 --*/
2094
2095 {
2096
2097 int Result;
2098 int ChildPid;
2099 struct epoll_event EpollControlEvent;
2100 struct epoll_event EpollWaitEvent[2];
2101 int SocketFd;
2102 int TmpFd;
2103 int EpollFd;
2104 LXT_SOCKET_PAIR SocketPair;
2105 int Status;
2106
2107 SocketPair.Parent = -1;
2108 SocketPair.Child = -1;
2109
2110 LxtCheckErrno(EpollFd = epoll_create1(EPOLL_CLOEXEC));
2111 LxtCheckResult(LxtSocketPairCreate(&SocketPair));
2112 LxtLogInfo("Created socket pair (%d, %d)", SocketPair.Parent, SocketPair.Child);
2113 EpollControlEvent.events = EPOLLET;
2114 EpollControlEvent.data.fd = SocketPair.Parent;
2115 LxtLogInfo("Adding socket pair (parent) (%d) file descriptor to epoll context", SocketPair.Parent);
2116
2117 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketPair.Parent, &EpollControlEvent));
2118
2119 LxtLogInfo("Adding socket pair (child) (%d) file descriptor to epoll context", SocketPair.Child);
2120
2121 EpollControlEvent.data.fd = SocketPair.Child;
2122 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketPair.Child, &EpollControlEvent));
2123
2124 LxtLogInfo("Forking...");
2125 LXT_SYNCHRONIZATION_POINT_START();
2126 LxtCheckErrno(ChildPid = fork());
2127 if (ChildPid == 0)
2128 {
2129 LXT_SYNCHRONIZATION_POINT();
2130
2131 LxtLogInfo("[Child] Waiting on epoll (EPOLLIN), should timeout");
2132 LxtCheckErrnoZeroSuccess(epoll_wait(EpollFd, EpollWaitEvent, 2, 1000));
2133
2134 LXT_SYNCHRONIZATION_POINT();
2135
2136 LxtLogInfo("[Child] Waiting on epoll (EPOLLIN)");
2137 LxtCheckErrno(Result = epoll_wait(EpollFd, EpollWaitEvent, 2, -1));
2138 LxtLogInfo("[Child] EPOLLIN received");
2139 LxtCheckEqual(Result, 1, "%d");
2140 LxtCheckEqual(EpollWaitEvent[0].data.fd, SocketPair.Child, "%d");
2141 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "0x%x");
2142 LxtCheckResult(LxtReceiveMessage(SocketPair.Child, "data"));
2143 LxtLogInfo("[Child] Received message");
2144
2145 LXT_SYNCHRONIZATION_POINT();
2146
2147 //
2148 // Wait for parent to send data.
2149 //
2150
2151 LXT_SYNCHRONIZATION_POINT();
2152 goto ErrorExit;
2153 }
2154
2155 LxtLogInfo("Sending data over socketpair");
2156 LxtCheckResult(LxtSendMessage(SocketPair.Parent, "data"));
2157
2158 LXT_SYNCHRONIZATION_POINT();
2159
2160 //
2161 // Let the child wait/timeout.
2162 //
2163
2164 LXT_SYNCHRONIZATION_POINT();
2165
2166 LxtLogInfo("Modifying the epoll to receive EPOLLIN events");
2167 EpollControlEvent.events = EPOLLIN | EPOLLET;
2168 EpollControlEvent.data.fd = SocketPair.Child;
2169 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_MOD, SocketPair.Child, &EpollControlEvent));
2170
2171 LXT_SYNCHRONIZATION_POINT();
2172
2173 //
2174 // Wait for child to receive data.
2175 //
2176
2177 LXT_SYNCHRONIZATION_POINT();
2178
2179 Result = 0;
2180
2181 ErrorExit:
2182 if (SocketPair.Parent != -1)
2183 {
2184 close(SocketPair.Parent);
2185 }
2186
2187 if (SocketPair.Child != -1)
2188 {
2189 close(SocketPair.Child);
2190 }
2191
2192 if (EpollFd != -1)
2193 {
2194 close(EpollFd);
2195 }
2196
2197 LXT_SYNCHRONIZATION_POINT_END();
2198 return Result;
2199 }
2200
2201 int EpollPhantomEventsTest(PLXT_ARGS Args)
2202
2203 /*++
2204 --*/
2205
2206 {
2207
2208 int Result;
2209 int ChildPid;
2210 struct epoll_event EpollControlEvent;
2211 struct epoll_event EpollWaitEvent[2];
2212 int SocketFd;
2213 int TmpFd;
2214 int EpollFd;
2215 LXT_SOCKET_PAIR SocketPair;
2216 int Status;
2217
2218 SocketPair.Parent = -1;
2219 SocketPair.Child = -1;
2220
2221 LxtCheckErrno(EpollFd = epoll_create1(EPOLL_CLOEXEC));
2222 LxtCheckResult(LxtSocketPairCreate(&SocketPair));
2223 LxtLogInfo("Created socket pair (%d, %d)", SocketPair.Parent, SocketPair.Child);
2224 EpollControlEvent.events = EPOLLIN | EPOLLET;
2225 EpollControlEvent.data.fd = SocketPair.Parent;
2226 LxtLogInfo("Adding socket pair (parent) (%d) file descriptor to epoll context", SocketPair.Parent);
2227
2228 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketPair.Parent, &EpollControlEvent));
2229
2230 LxtLogInfo("Adding socket pair (child) (%d) file descriptor to epoll context", SocketPair.Child);
2231
2232 EpollControlEvent.data.fd = SocketPair.Child;
2233 LxtCheckErrno(epoll_ctl(EpollFd, EPOLL_CTL_ADD, SocketPair.Child, &EpollControlEvent));
2234
2235 LxtLogInfo("Forking...");
2236 LXT_SYNCHRONIZATION_POINT_START();
2237 LxtCheckErrno(ChildPid = fork());
2238 if (ChildPid == 0)
2239 {
2240 LxtLogInfo("[Child] Waiting on epoll (EPOLLIN)");
2241 LxtCheckErrno(Result = epoll_wait(EpollFd, EpollWaitEvent, 2, -1));
2242 LxtCheckEqual(Result, 1, "%d");
2243 LxtCheckEqual(EpollWaitEvent[0].data.fd, SocketPair.Child, "%d");
2244 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "0x%x");
2245 LxtLogInfo("[Child] Waiting on message");
2246 LxtCheckResult(LxtReceiveMessage(SocketPair.Child, "data"));
2247
2248 LxtLogInfo("Closing (%d) file descriptor", SocketPair.Child);
2249 TmpFd = SocketPair.Child;
2250 LxtClose(SocketPair.Child);
2251
2252 LxtCheckErrno(SocketFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
2253 LxtLogInfo("Created (%d) file descriptor, that should be the same as closed fd (%d)", SocketFd, TmpFd);
2254
2255 LXT_SYNCHRONIZATION_POINT();
2256
2257 //
2258 // Wait for parent to send data.
2259 //
2260
2261 LXT_SYNCHRONIZATION_POINT();
2262
2263 LxtLogInfo("Waiting on epoll phantom event (EPOLLIN)");
2264 LxtCheckErrno(Result = epoll_wait(EpollFd, EpollWaitEvent, 2, -1));
2265 LxtCheckEqual(Result, 1, "%d");
2266 LxtCheckEqual(EpollWaitEvent[0].data.fd, SocketPair.Child, "%d");
2267 LxtCheckEqual(EpollWaitEvent[0].events, EPOLLIN, "0x%x");
2268
2269 LXT_SYNCHRONIZATION_POINT();
2270 goto ErrorExit;
2271 }
2272
2273 LxtLogInfo("Sending data over socketpair");
2274 LxtCheckResult(LxtSendMessage(SocketPair.Parent, "data"));
2275
2276 //
2277 // Verify that both only child receives the same EPOLLIN event.
2278 //
2279
2280 sleep(1);
2281 LxtLogInfo("Waiting on epoll (EPOLLIN) (should fail)");
2282 LxtCheckErrno(Result = epoll_wait(EpollFd, EpollWaitEvent, 2, 100));
2283 LxtCheckEqual(Result, 0, "%d");
2284
2285 LXT_SYNCHRONIZATION_POINT();
2286
2287 LxtCheckResult(LxtSendMessage(SocketPair.Parent, "data"));
2288
2289 LXT_SYNCHRONIZATION_POINT();
2290
2291 //
2292 // Wait for child to receive phantom event.
2293 //
2294
2295 LXT_SYNCHRONIZATION_POINT();
2296
2297 Result = 0;
2298
2299 ErrorExit:
2300 if (SocketPair.Parent != -1)
2301 {
2302 close(SocketPair.Parent);
2303 }
2304
2305 if (SocketPair.Child != -1)
2306 {
2307 close(SocketPair.Child);
2308 }
2309
2310 if (EpollFd != -1)
2311 {
2312 close(EpollFd);
2313 }
2314
2315 LXT_SYNCHRONIZATION_POINT_END();
2316 return Result;
2317 }
2318
2319 int PPollInvalidArgument(PLXT_ARGS Args)
2320
2321 {
2322
2323 int FileDescriptor1;
2324 struct pollfd PollDescriptors[4];
2325 int Result;
2326 struct timespec Timeout;
2327
2328 LxtCheckResult(FileDescriptor1 = open("/data/test/poll_test.bin", O_RDWR | O_CREAT, S_IRWXU));
2329 PollDescriptors[0].fd = FileDescriptor1;
2330 PollDescriptors[0].events = POLLIN;
2331 PollDescriptors[0].revents = -1;
2332
2333 //
2334 // Invalid argument variations.
2335 //
2336
2337 memset(&Timeout, 0, sizeof(Timeout));
2338 Timeout.tv_sec = -1;
2339 LxtCheckErrnoFailure(ppoll(PollDescriptors, 1, &Timeout, NULL), EINVAL);
2340 memset(&Timeout, 0, sizeof(Timeout));
2341 Timeout.tv_nsec = 999999999 + 1;
2342 LxtCheckErrnoFailure(ppoll(PollDescriptors, 1, &Timeout, NULL), EINVAL);
2343
2344 ErrorExit:
2345 if (FileDescriptor1 != -1)
2346 {
2347 LxtClose(FileDescriptor1);
2348 }
2349
2350 return Result;
2351 }
2352
2353 int EpollUnalignedTest(PLXT_ARGS Args)
2354
2355 {
2356
2357 char Buffer[sizeof(struct pollfd) + 1];
2358 int FileDescriptor1;
2359 struct pollfd* PollDescriptors;
2360 int Result;
2361 struct timespec Timeout;
2362
2363 //
2364 // Set up the poll descriptors array to be unaligned.
2365 //
2366
2367 PollDescriptors = (struct pollfd*)&Buffer[1];
2368 LxtLogInfo("PollDescriptors address %p", PollDescriptors);
2369
2370 LxtCheckResult(FileDescriptor1 = open("/data/test/poll_test.bin", O_RDWR | O_CREAT, S_IRWXU));
2371 PollDescriptors[0].fd = FileDescriptor1;
2372 PollDescriptors[0].events = POLLIN;
2373 PollDescriptors[0].revents = -1;
2374 memset(&Timeout, 0, sizeof(Timeout));
2375 Timeout.tv_sec = 1;
2376 LxtCheckErrno(ppoll(PollDescriptors, 1, &Timeout, NULL));
2377
2378 ErrorExit:
2379 if (FileDescriptor1 != -1)
2380 {
2381 LxtClose(FileDescriptor1);
2382 }
2383
2384 return Result;
2385 }
2386
2387 int EpollDeleteCloseFdLoop(PLXT_ARGS Args)
2388
2389 /*++
2390
2391 Routine Description:
2392
2393 This routine loops\stresses the removal of EPOLL FD and closing of the FD.
2394
2395 Arguments:
2396
2397 Args - Supplies the command line arguments.
2398
2399 Return Value:
2400
2401 Returns 0 on success, -1 on failure.
2402
2403 --*/
2404
2405 {
2406
2407 char Buffer[10];
2408 int ChildPid;
2409 struct epoll_event EpollControlEvent;
2410 const int NumFd = 100;
2411 int EpollFd[NumFd];
2412 int Iterator;
2413 int Loop;
2414 int NestedEpollFd[NumFd];
2415 int PipeFileDescriptors[2] = {-1, -1};
2416 int Result;
2417 int SharedEpollFd;
2418 int SocketFd[NumFd];
2419 int Status;
2420
2421 //
2422 // Initialize locals.
2423 //
2424
2425 ChildPid = -1;
2426 for (Iterator = 0; Iterator < NumFd; Iterator++)
2427 {
2428 SocketFd[Iterator] = -1;
2429 EpollFd[Iterator] = -1;
2430 NestedEpollFd[Iterator] = -1;
2431 }
2432
2433 LxtCheckErrnoZeroSuccess(pipe(PipeFileDescriptors));
2434 LxtCheckErrno(write(PipeFileDescriptors[1], "\n", 1));
2435 LxtCheckErrno(SharedEpollFd = epoll_create1(0));
2436
2437 //
2438 // Start a loop to read the pipe, thereby triggering a notification.
2439 //
2440
2441 LxtCheckErrno(ChildPid = fork());
2442 if (ChildPid == 0)
2443 {
2444 LxtCheckClose(PipeFileDescriptors[1]);
2445 while ((Result = read(PipeFileDescriptors[0], Buffer, sizeof(Buffer))) > 0)
2446 ;
2447
2448 //
2449 // The loop should terminate when the other threads exit and
2450 // close the write pipe handle.
2451 //
2452
2453 LxtCheckErrno(Result);
2454 goto ErrorExit;
2455 }
2456
2457 for (Loop = 0; Loop < 50; Loop++)
2458 {
2459 for (Iterator = 0; Iterator < NumFd; Iterator++)
2460 {
2461 LxtCheckErrno(EpollFd[Iterator] = epoll_create1(0));
2462 LxtCheckErrno(NestedEpollFd[Iterator] = epoll_create1(0));
2463 LxtCheckErrno(SocketFd[Iterator] = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0));
2464
2465 EpollControlEvent.events = EPOLLIN | EPOLLET;
2466 EpollControlEvent.data.fd = SocketFd[Iterator];
2467 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_ADD, SocketFd[Iterator], &EpollControlEvent));
2468
2469 EpollControlEvent.events = EPOLLIN;
2470 EpollControlEvent.data.fd = PipeFileDescriptors[0];
2471 LxtCheckErrno(epoll_ctl(NestedEpollFd[Iterator], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
2472
2473 EpollControlEvent.events = EPOLLIN;
2474 EpollControlEvent.data.fd = NestedEpollFd[Iterator];
2475 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_ADD, NestedEpollFd[Iterator], &EpollControlEvent));
2476
2477 EpollControlEvent.events = EPOLLIN;
2478 EpollControlEvent.data.fd = EpollFd[Iterator];
2479 LxtCheckErrno(epoll_ctl(SharedEpollFd, EPOLL_CTL_ADD, EpollFd[Iterator], &EpollControlEvent));
2480 }
2481
2482 LXT_SYNCHRONIZATION_POINT_START();
2483 LxtCheckErrno(ChildPid = fork());
2484 if (ChildPid == 0)
2485 {
2486
2487 for (Iterator = 0; Iterator < NumFd; Iterator++)
2488 {
2489 LxtClose(NestedEpollFd[Iterator]);
2490 NestedEpollFd[Iterator] = -1;
2491 LxtClose(SocketFd[Iterator]);
2492 SocketFd[Iterator] = -1;
2493 }
2494
2495 //
2496 // The race is between releasing the last reference to the file
2497 // descriptor here and releasing the last reference to EPOLL by
2498 // the child. Synchronize to keep the race as close as possible.
2499 //
2500
2501 LXT_SYNCHRONIZATION_POINT();
2502 for (Iterator = 0; Iterator < NumFd; Iterator++)
2503 {
2504 LxtClose(EpollFd[Iterator]);
2505 EpollFd[Iterator] = -1;
2506 }
2507
2508 _exit(0);
2509 }
2510
2511 for (Iterator = 0; Iterator < NumFd; Iterator++)
2512 {
2513 LxtClose(EpollFd[Iterator]);
2514 EpollFd[Iterator] = -1;
2515 }
2516
2517 //
2518 // See the above comment about synchronizing to keep the race close.
2519 //
2520
2521 LXT_SYNCHRONIZATION_POINT();
2522 for (Iterator = 0; Iterator < NumFd; Iterator++)
2523 {
2524 LxtCheckErrno(write(PipeFileDescriptors[1], "\n", 1));
2525 LxtClose(NestedEpollFd[Iterator]);
2526 NestedEpollFd[Iterator] = -1;
2527 LxtClose(SocketFd[Iterator]);
2528 SocketFd[Iterator] = -1;
2529 }
2530
2531 LxtCheckResult(LxtWaitPidPoll(ChildPid, 0));
2532 }
2533
2534 Result = LXT_RESULT_SUCCESS;
2535
2536 ErrorExit:
2537 if (PipeFileDescriptors[1] != -1)
2538 {
2539 close(PipeFileDescriptors[1]);
2540 }
2541
2542 if (PipeFileDescriptors[0] != -1)
2543 {
2544 close(PipeFileDescriptors[0]);
2545 }
2546
2547 if (SharedEpollFd != -1)
2548 {
2549 close(SharedEpollFd);
2550 }
2551
2552 for (Iterator = 0; Iterator < NumFd; Iterator++)
2553 {
2554
2555 //
2556 // Only close socket FD's in the parent because socket FD's are created
2557 // with CLOSE_ON_EXEC and so are only valid in the parent.
2558 //
2559
2560 if ((SocketFd[Iterator] != -1) && (ChildPid != 0))
2561 {
2562 close(SocketFd[Iterator]);
2563 }
2564
2565 if ((NestedEpollFd[Iterator] != -1) && (ChildPid != 0))
2566 {
2567 close(NestedEpollFd[Iterator]);
2568 }
2569
2570 if (EpollFd[Iterator] != -1)
2571 {
2572 close(EpollFd[Iterator]);
2573 }
2574 }
2575
2576 if (ChildPid == 0)
2577 {
2578 _exit(0);
2579 }
2580
2581 return Result;
2582 }
2583
2584 void* EpollDup2FdLoopThread(void* Parameter)
2585
2586 /*++
2587
2588 Description:
2589
2590 This routine is the thread handler for the EpollDup2FdLoop test.
2591
2592 Arguments:
2593
2594 Parameter - Supplies the thread parameter.
2595
2596 Return Value:
2597
2598 Returns the thread id on success, -1 on failure.
2599
2600 --*/
2601
2602 {
2603
2604 PEPOLL_DUP2_CONTEXT Context;
2605 struct epoll_event EpollControlEvent;
2606 int Iterator;
2607 int Loop;
2608 int Result;
2609
2610 Context = (PEPOLL_DUP2_CONTEXT)Parameter;
2611 for (Loop = 0; Loop < 50; Loop++)
2612 {
2613 for (Iterator = 0; Iterator < EPOLL_DUP2_FD_COUNT; Iterator++)
2614 {
2615 LXT_SYNCHRONIZATION_POINT_CHILD();
2616 EpollControlEvent.events = EPOLLIN;
2617 EpollControlEvent.data.fd = Context->Fd[Iterator];
2618 if (epoll_ctl(Context->EpollFd, EPOLL_CTL_DEL, Context->Fd[Iterator], &EpollControlEvent) != 0)
2619 {
2620
2621 Result = errno;
2622
2623 //
2624 // Race with parent is expected to cause the fd to be invalid
2625 // at times (not the same file that was added).
2626 //
2627
2628 if (Result == EINVAL)
2629 {
2630 Result = LXT_RESULT_SUCCESS;
2631 }
2632
2633 LxtCheckResult(Result);
2634 }
2635 }
2636 }
2637
2638 Result = LXT_RESULT_SUCCESS;
2639
2640 ErrorExit:
2641 LXT_SYNCHRONIZATION_POINT_PTHREAD_END_THREAD();
2642
2643 #pragma GCC diagnostic push
2644 #pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
2645
2646 return (void*)Result;
2647
2648 #pragma GCC diagnostic pop
2649 }
2650
2651 int EpollDup2FdLoop(PLXT_ARGS Args)
2652
2653 /*++
2654
2655 Routine Description:
2656
2657 This routine loops\stresses epoll operations on fd's that are being closed
2658 by other threads. The close is done via dup2 because dup2 also holds the
2659 filetable lock, increasing the chances of hitting locking issues.
2660
2661 Arguments:
2662
2663 Args - Supplies the command line arguments.
2664
2665 Return Value:
2666
2667 Returns 0 on success, -1 on failure.
2668
2669 --*/
2670
2671 {
2672
2673 struct epoll_event EpollControlEvent;
2674 EPOLL_DUP2_CONTEXT Context;
2675 int Iterator;
2676 int Loop;
2677 int NullFd;
2678 const int NumFd = EPOLL_DUP2_FD_COUNT;
2679 int Result;
2680 void* Status;
2681 pthread_t Thread = 0;
2682
2683 //
2684 // Initialize locals.
2685 //
2686
2687 Context.EpollFd = -1;
2688 for (Iterator = 0; Iterator < NumFd; Iterator++)
2689 {
2690 Context.Fd[Iterator] = -1;
2691 }
2692
2693 LxtCheckErrno(NullFd = open("/dev/null", O_RDWR));
2694 LxtCheckErrno(Context.EpollFd = epoll_create1(0));
2695 LXT_SYNCHRONIZATION_POINT_START();
2696 LxtCheckResultError(pthread_create(&Thread, NULL, EpollDup2FdLoopThread, &Context));
2697
2698 for (Loop = 0; Loop < 50; Loop++)
2699 {
2700 for (Iterator = 0; Iterator < NumFd; Iterator++)
2701 {
2702 LxtCheckErrno(Context.Fd[Iterator] = open("/dev/null", O_RDWR));
2703 EpollControlEvent.events = EPOLLIN | EPOLLET;
2704 EpollControlEvent.data.fd = Context.Fd[Iterator];
2705 LxtCheckErrno(epoll_ctl(Context.EpollFd, EPOLL_CTL_ADD, Context.Fd[Iterator], &EpollControlEvent));
2706 }
2707
2708 for (Iterator = 0; Iterator < NumFd; Iterator++)
2709 {
2710 LXT_SYNCHRONIZATION_POINT_PARENT();
2711 LxtCheckErrno(dup2(NullFd, Context.Fd[Iterator]));
2712 }
2713
2714 for (Iterator = 0; Iterator < NumFd; Iterator++)
2715 {
2716 LxtClose(Context.Fd[Iterator]);
2717 Context.Fd[Iterator] = -1;
2718 }
2719 }
2720
2721 pthread_join(Thread, (void**)&Result);
2722 Thread = 0;
2723 LxtCheckResult(Result);
2724
2725 ErrorExit:
2726 LXT_SYNCHRONIZATION_POINT_PTHREAD_END_PARENT(Thread);
2727 for (Iterator = 0; Iterator < NumFd; Iterator++)
2728 {
2729 if (Context.Fd[Iterator] != -1)
2730 {
2731 close(Context.Fd[Iterator]);
2732 }
2733 }
2734
2735 if (Context.EpollFd != -1)
2736 {
2737 close(Context.EpollFd);
2738 }
2739
2740 if (NullFd != -1)
2741 {
2742 close(NullFd);
2743 }
2744
2745 return Result;
2746 }
2747
2748 int EpollRelatedFileStress(PLXT_ARGS Args)
2749
2750 /*++
2751
2752 Routine Description:
2753
2754 This routine loops\stresses the usage of multiple epoll files containing
2755 the same set of fds.
2756
2757 Arguments:
2758
2759 Args - Supplies the command line arguments.
2760
2761 Return Value:
2762
2763 Returns 0 on success, -1 on failure.
2764
2765 --*/
2766
2767 {
2768
2769 int AddRemoveLoop;
2770 char Buffer[10];
2771 int ChildPid;
2772 struct epoll_event EpollControlEvent[3];
2773 int EpollFd[2];
2774 int Iterator;
2775 int Loop;
2776 int MasterEpollFd;
2777 int Result;
2778 int SharedEpollFd;
2779 int Status;
2780
2781 //
2782 // Initialize locals.
2783 //
2784
2785 ChildPid = -1;
2786 MasterEpollFd = -1;
2787 for (Iterator = 0; Iterator < LXT_COUNT_OF(EpollFd); Iterator++)
2788 {
2789 EpollFd[Iterator] = -1;
2790 }
2791
2792 LxtCheckErrno(MasterEpollFd = epoll_create1(0));
2793 for (Iterator = 0; Iterator < LXT_COUNT_OF(EpollFd); Iterator++)
2794 {
2795 LxtCheckErrno(EpollFd[Iterator] = epoll_create1(0));
2796 EpollControlEvent[0].events = EPOLLIN;
2797 EpollControlEvent[0].data.fd = EpollFd[Iterator];
2798 LxtCheckErrno(epoll_ctl(MasterEpollFd, EPOLL_CTL_ADD, EpollFd[Iterator], EpollControlEvent));
2799 }
2800
2801 LXT_SYNCHRONIZATION_POINT_START();
2802 LxtCheckErrno(ChildPid = fork());
2803 for (Loop = 0; Loop < 2000; Loop++)
2804 {
2805 if (ChildPid == 0)
2806 {
2807
2808 //
2809 // Synchronize with the wait loop to try to increase the
2810 // chances of hitting a race.
2811 //
2812
2813 LXT_SYNCHRONIZATION_POINT();
2814 for (AddRemoveLoop = 0; AddRemoveLoop < LXT_COUNT_OF(EpollControlEvent); AddRemoveLoop++)
2815 {
2816
2817 for (Iterator = 0; Iterator < LXT_COUNT_OF(EpollFd); Iterator++)
2818 {
2819
2820 EpollControlEvent[0].events = EPOLLIN;
2821 EpollControlEvent[0].data.fd = 0;
2822 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_ADD, 0, EpollControlEvent));
2823
2824 EpollControlEvent[0].events = EPOLLOUT;
2825 EpollControlEvent[0].data.fd = 1;
2826 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_ADD, 1, EpollControlEvent));
2827
2828 EpollControlEvent[0].events = EPOLLOUT;
2829 EpollControlEvent[0].data.fd = 2;
2830 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_ADD, 2, EpollControlEvent));
2831 }
2832
2833 for (Iterator = 0; Iterator < LXT_COUNT_OF(EpollFd); Iterator++)
2834 {
2835
2836 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_DEL, 0, NULL));
2837
2838 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_DEL, 1, NULL));
2839
2840 LxtCheckErrno(epoll_ctl(EpollFd[Iterator], EPOLL_CTL_DEL, 2, NULL));
2841 }
2842 }
2843 }
2844 else
2845 {
2846 LXT_SYNCHRONIZATION_POINT();
2847 (void)epoll_wait(MasterEpollFd, EpollControlEvent, LXT_COUNT_OF(EpollControlEvent), 1);
2848
2849 for (Iterator = 0; Iterator < LXT_COUNT_OF(EpollFd); Iterator++)
2850 {
2851 (void)epoll_wait(EpollFd[Iterator], EpollControlEvent, LXT_COUNT_OF(EpollControlEvent), 1);
2852 }
2853 }
2854 }
2855
2856 ErrorExit:
2857 LXT_SYNCHRONIZATION_POINT_END();
2858 for (Iterator = 0; Iterator < LXT_COUNT_OF(EpollFd); Iterator++)
2859 {
2860 if (EpollFd[Iterator] != -1)
2861 {
2862 close(EpollFd[Iterator]);
2863 }
2864 }
2865
2866 if (MasterEpollFd != -1)
2867 {
2868 close(MasterEpollFd);
2869 }
2870
2871 return Result;
2872 }
2873
2874 int EpollRecursionTest(PLXT_ARGS Args)
2875
2876 /*++
2877
2878 Routine Description:
2879
2880 This routine verifies epoll file included in epoll file behavior.
2881
2882 Arguments:
2883
2884 Args - Supplies the command line arguments.
2885
2886 Return Value:
2887
2888 Returns 0 on success, -1 on failure.
2889
2890 --*/
2891
2892 {
2893
2894 char Buffer[10];
2895 struct epoll_event EpollControlEvent;
2896 int EpollFileDescriptor;
2897 int EpollContainerFd;
2898 int EpollContainer2Fd;
2899 struct epoll_event EpollWaitEvent;
2900 struct epoll_event* InputEvent;
2901 struct epoll_event* OutputEvent;
2902 int PipeFileDescriptors[2] = {-1, -1};
2903 int PipeFileDescriptors2[2] = {-1, -1};
2904 fd_set ReadFds;
2905 int Result;
2906 struct timeval Timeout;
2907 fd_set WriteFds;
2908
2909 //
2910 // Initialize locals.
2911 //
2912
2913 EpollFileDescriptor = -1;
2914 EpollContainerFd = -1;
2915 EpollContainer2Fd = -1;
2916
2917 //
2918 // Create two epoll files.
2919 //
2920
2921 LxtCheckErrno(EpollFileDescriptor = epoll_create(1));
2922 LxtCheckErrno(EpollContainerFd = epoll_create(1));
2923
2924 //
2925 // Open a pipe to test epoll.
2926 //
2927
2928 LxtCheckErrnoZeroSuccess(pipe(PipeFileDescriptors));
2929 LxtCheckErrnoZeroSuccess(pipe(PipeFileDescriptors2));
2930
2931 //
2932 // Pend a write.
2933 //
2934
2935 LxtCheckErrno(write(PipeFileDescriptors[1], "\n", 1));
2936
2937 //
2938 // Add one epoll file to the other.
2939 //
2940
2941 EpollControlEvent.events = EPOLLIN;
2942 EpollControlEvent.data.fd = EpollFileDescriptor;
2943 LxtCheckErrno(epoll_ctl(EpollContainerFd, EPOLL_CTL_ADD, EpollFileDescriptor, &EpollControlEvent));
2944
2945 //
2946 // Now attempt to add them in reverse order to create a simple loop.
2947 //
2948
2949 EpollControlEvent.events = EPOLLIN;
2950 EpollControlEvent.data.fd = EpollContainerFd;
2951 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, EpollContainerFd, &EpollControlEvent), ELOOP);
2952
2953 //
2954 // Attempt to modify swapping the container/included descriptors.
2955 //
2956
2957 EpollControlEvent.events = EPOLLIN;
2958 EpollControlEvent.data.fd = EpollContainerFd;
2959 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_MOD, EpollContainerFd, &EpollControlEvent), ENOENT);
2960
2961 //
2962 // Attempt to delete swapping the container/included descriptors.
2963 //
2964
2965 EpollControlEvent.data.fd = EpollContainerFd;
2966 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_DEL, EpollContainerFd, NULL), ENOENT);
2967
2968 //
2969 // Add the read pipe end to the epoll.
2970 //
2971
2972 EpollControlEvent.events = EPOLLIN;
2973 EpollControlEvent.data.fd = PipeFileDescriptors[0];
2974 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
2975
2976 //
2977 // Verify the epoll is signalled.
2978 //
2979
2980 memset(&Timeout, 0, sizeof(Timeout));
2981 FD_ZERO(&ReadFds);
2982 FD_SET(EpollFileDescriptor, &ReadFds);
2983 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
2984 LxtCheckEqual(Result, 1, "%d");
2985
2986 //
2987 // Add the second pipe, which is not read ready.
2988 //
2989
2990 EpollControlEvent.events = EPOLLIN;
2991 EpollControlEvent.data.fd = PipeFileDescriptors[0];
2992 LxtCheckErrno(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, PipeFileDescriptors2[0], &EpollControlEvent));
2993
2994 //
2995 // Verify the epoll remains signalled.
2996 //
2997
2998 memset(&Timeout, 0, sizeof(Timeout));
2999 FD_ZERO(&ReadFds);
3000 FD_SET(EpollFileDescriptor, &ReadFds);
3001 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
3002 LxtCheckEqual(Result, 1, "%d");
3003
3004 //
3005 // Pend a write to the other pipe.
3006 //
3007
3008 LxtCheckErrno(write(PipeFileDescriptors2[1], "\n", 1));
3009
3010 //
3011 // Verify the epoll remains signalled.
3012 //
3013
3014 memset(&Timeout, 0, sizeof(Timeout));
3015 FD_ZERO(&ReadFds);
3016 FD_SET(EpollFileDescriptor, &ReadFds);
3017 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
3018 LxtCheckEqual(Result, 1, "%d");
3019
3020 //
3021 // Create another epoll containing the first.
3022 //
3023
3024 LxtCheckErrno(EpollContainerFd = epoll_create(1));
3025
3026 //
3027 // Add the first epoll.
3028 //
3029
3030 EpollControlEvent.events = EPOLLIN;
3031 EpollControlEvent.data.fd = EpollFileDescriptor;
3032 LxtCheckErrno(epoll_ctl(EpollContainerFd, EPOLL_CTL_ADD, EpollFileDescriptor, &EpollControlEvent));
3033
3034 //
3035 // Try to add the second back to the first to create a loop.
3036 //
3037
3038 EpollControlEvent.events = EPOLLIN;
3039 EpollControlEvent.data.fd = EpollContainerFd;
3040 LxtCheckErrnoFailure(epoll_ctl(EpollFileDescriptor, EPOLL_CTL_ADD, EpollContainerFd, &EpollControlEvent), ELOOP);
3041
3042 //
3043 // The first epoll should trigger the second.
3044 //
3045
3046 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3047 LxtCheckEqual(Result, 1, "%d");
3048
3049 //
3050 // Add the second pipe directly to the container epoll.
3051 //
3052
3053 EpollControlEvent.events = EPOLLIN;
3054 EpollControlEvent.data.fd = PipeFileDescriptors2[0];
3055 LxtCheckErrno(epoll_ctl(EpollContainerFd, EPOLL_CTL_ADD, PipeFileDescriptors2[0], &EpollControlEvent));
3056
3057 //
3058 // The epoll should remain signalled.
3059 //
3060
3061 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3062 LxtCheckEqual(Result, 1, "%d");
3063
3064 //
3065 // Create yet another epoll to test non-read signals.
3066 //
3067
3068 LxtCheckErrno(EpollContainer2Fd = epoll_create(1));
3069 EpollControlEvent.events = EPOLLOUT;
3070 EpollControlEvent.data.fd = EpollFileDescriptor;
3071 LxtCheckErrno(epoll_ctl(EpollContainer2Fd, EPOLL_CTL_ADD, EpollFileDescriptor, &EpollControlEvent));
3072
3073 FD_ZERO(&WriteFds);
3074 FD_SET(EpollContainer2Fd, &WriteFds);
3075 memset(&Timeout, 0, sizeof(Timeout));
3076 LxtCheckErrno(select((EpollContainer2Fd + 1), NULL, &WriteFds, NULL, &Timeout));
3077 LxtCheckEqual(Result, 0, "%d");
3078 LxtCheckErrno(epoll_wait(EpollContainer2Fd, &EpollWaitEvent, 1, 0));
3079 LxtCheckEqual(Result, 0, "%d");
3080
3081 //
3082 // Clear the signal for the second pipe and verify signal state.
3083 //
3084
3085 LxtCheckErrno(read(PipeFileDescriptors2[0], Buffer, sizeof(Buffer)));
3086 FD_SET(EpollFileDescriptor, &ReadFds);
3087 memset(&Timeout, 0, sizeof(Timeout));
3088 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
3089 LxtCheckEqual(Result, 1, "%d");
3090 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3091 LxtCheckEqual(Result, 1, "%d");
3092
3093 //
3094 // Clear the signal for the first pipe and verify signal state.
3095 //
3096
3097 LxtCheckErrno(read(PipeFileDescriptors[0], Buffer, sizeof(Buffer)));
3098 FD_SET(EpollFileDescriptor, &ReadFds);
3099 memset(&Timeout, 0, sizeof(Timeout));
3100 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
3101 LxtCheckEqual(Result, 0, "%d");
3102 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3103 LxtCheckEqual(Result, 0, "%d");
3104
3105 //
3106 // Signal both pipes again.
3107 //
3108
3109 LxtCheckErrno(write(PipeFileDescriptors2[1], "\n", 1));
3110 LxtCheckErrno(write(PipeFileDescriptors2[1], "\n", 1));
3111
3112 //
3113 // Verify signal.
3114 //
3115
3116 FD_SET(EpollFileDescriptor, &ReadFds);
3117 memset(&Timeout, 0, sizeof(Timeout));
3118 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
3119 LxtCheckEqual(Result, 1, "%d");
3120 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3121 LxtCheckEqual(Result, 1, "%d");
3122
3123 //
3124 // Remove the second pipe from the container and check signal state again.
3125 //
3126
3127 LxtCheckErrno(epoll_ctl(EpollContainerFd, EPOLL_CTL_DEL, PipeFileDescriptors2[0], NULL));
3128
3129 FD_SET(EpollFileDescriptor, &ReadFds);
3130 memset(&Timeout, 0, sizeof(Timeout));
3131 LxtCheckErrno(select((EpollFileDescriptor + 1), &ReadFds, NULL, NULL, &Timeout));
3132 LxtCheckEqual(Result, 1, "%d");
3133 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3134 LxtCheckEqual(Result, 1, "%d");
3135
3136 //
3137 // Close the nested epoll and verify signal state.
3138 //
3139
3140 LxtCheckClose(EpollFileDescriptor);
3141 LxtCheckErrno(epoll_wait(EpollContainerFd, &EpollWaitEvent, 1, 0));
3142 LxtCheckEqual(Result, 0, "%d");
3143
3144 ErrorExit:
3145 if (EpollContainer2Fd != -1)
3146 {
3147 close(EpollContainer2Fd);
3148 }
3149
3150 if (EpollFileDescriptor != -1)
3151 {
3152 close(EpollFileDescriptor);
3153 }
3154
3155 if (EpollContainerFd != -1)
3156 {
3157 close(EpollContainerFd);
3158 }
3159
3160 if (PipeFileDescriptors2[1] != -1)
3161 {
3162 close(PipeFileDescriptors2[1]);
3163 }
3164
3165 if (PipeFileDescriptors2[0] != -1)
3166 {
3167 close(PipeFileDescriptors2[0]);
3168 }
3169
3170 if (PipeFileDescriptors[1] != -1)
3171 {
3172 close(PipeFileDescriptors[1]);
3173 }
3174
3175 if (PipeFileDescriptors[0] != -1)
3176 {
3177 close(PipeFileDescriptors[0]);
3178 }
3179
3180 return Result;
3181 }
3182
3183 int EpollRecursionLimitTest(PLXT_ARGS Args)
3184
3185 /*++
3186
3187 Routine Description:
3188
3189 This routine checks for an upper limit of recursive epolls.
3190
3191 Arguments:
3192
3193 Args - Supplies the command line arguments.
3194
3195 Return Value:
3196
3197 Returns 0 on success, -1 on failure.
3198
3199 --*/
3200
3201 {
3202
3203 #define EPOLL_MAX_RECURSION_COUNT 6
3204 #define EPOLL_CHAIN_COUNT 50
3205
3206 int ChainIndex;
3207 struct epoll_event EpollControlEvent;
3208 int EpollFds[EPOLL_CHAIN_COUNT][EPOLL_MAX_RECURSION_COUNT];
3209 int EpollContentFds[EPOLL_MAX_RECURSION_COUNT];
3210 struct epoll_event EpollWaitEvent;
3211 int ExtraEpollFd;
3212 int Index;
3213 int PipeFileDescriptors[2] = {-1, -1};
3214 int Result;
3215
3216 //
3217 // Initialize locals.
3218 //
3219
3220 ExtraEpollFd = -1;
3221 memset(EpollFds, -1, sizeof(EpollFds));
3222 memset(EpollContentFds, -1, sizeof(EpollContentFds));
3223 memset(&EpollControlEvent, 0, sizeof(EpollControlEvent));
3224 memset(&EpollWaitEvent, 0, sizeof(EpollWaitEvent));
3225 EpollControlEvent.events = EPOLLIN;
3226 LxtCheckErrnoZeroSuccess(pipe(PipeFileDescriptors));
3227
3228 for (ChainIndex = 0; ChainIndex < EPOLL_CHAIN_COUNT; ChainIndex += 1)
3229 {
3230 for (Index = 0; Index < EPOLL_MAX_RECURSION_COUNT; Index += 1)
3231 {
3232
3233 //
3234 // Create a new epoll.
3235 //
3236
3237 LxtCheckErrno(EpollFds[ChainIndex][Index] = epoll_create(1));
3238
3239 //
3240 // Add the previous epoll to make a chain.
3241 //
3242
3243 if (Index > 0)
3244 {
3245 LxtCheckErrno(epoll_ctl(EpollFds[ChainIndex][Index], EPOLL_CTL_ADD, EpollFds[ChainIndex][Index - 1], &EpollControlEvent));
3246 }
3247 }
3248 }
3249
3250 LxtCheckErrno(ExtraEpollFd = epoll_create(1));
3251
3252 //
3253 // Attempt to add an epoll exceeding the maximum depth.
3254 //
3255
3256 LxtCheckErrnoFailure(epoll_ctl(ExtraEpollFd, EPOLL_CTL_ADD, EpollFds[0][Index - 1], &EpollControlEvent), ELOOP);
3257
3258 //
3259 // Add a pipe file descriptor.
3260 //
3261
3262 LxtCheckErrno(epoll_ctl(EpollFds[0][5], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
3263
3264 //
3265 // Try creating a chain with a regular file descriptor in it.
3266 //
3267
3268 for (Index = 0; Index < (EPOLL_MAX_RECURSION_COUNT - 1); Index += 1)
3269 {
3270
3271 //
3272 // Create a new epoll.
3273 //
3274
3275 LxtCheckErrno(EpollContentFds[Index] = epoll_create(1));
3276
3277 //
3278 // Add a regular file descriptor.
3279 //
3280
3281 LxtCheckErrno(epoll_ctl(EpollContentFds[Index], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
3282
3283 //
3284 // Add the previous epoll to make a chain.
3285 //
3286
3287 if (Index > 0)
3288 {
3289 LxtCheckErrno(epoll_ctl(EpollContentFds[Index], EPOLL_CTL_ADD, EpollContentFds[Index - 1], &EpollControlEvent));
3290 }
3291 }
3292
3293 //
3294 // A non-epoll file descriptor is not allowed to be nested deeper
3295 // than EPOLL_MAX_RECURSION_COUNT. There is a pipe file descriptor
3296 // at [0][0] so this add attempt is expected to fail.
3297 //
3298
3299 LxtCheckErrno(EpollContentFds[Index] = epoll_create(1));
3300 LxtCheckErrnoFailure(epoll_ctl(EpollContentFds[Index], EPOLL_CTL_ADD, EpollContentFds[Index - 1], &EpollControlEvent), EINVAL);
3301
3302 //
3303 // Attempt to link chains together, where each add stays below the limit
3304 // but the total chain size becomes increasingly large.
3305 //
3306
3307 for (ChainIndex = (EPOLL_CHAIN_COUNT - 1); ChainIndex > 0; ChainIndex -= 1)
3308 {
3309 LxtLogInfo("[%d][%d] -> [%d][%d]", ChainIndex, 0, ChainIndex - 1, Index - 2);
3310 LxtCheckErrno(epoll_ctl(EpollFds[ChainIndex][0], EPOLL_CTL_ADD, EpollFds[ChainIndex - 1][Index - 2], &EpollControlEvent));
3311 }
3312
3313 //
3314 // Now try to introduce a loop into this extra-large chain.
3315 //
3316
3317 LxtCheckErrnoFailure(epoll_ctl(EpollFds[0][0], EPOLL_CTL_ADD, EpollFds[1][0], &EpollControlEvent), ELOOP);
3318
3319 LxtCheckErrnoFailure(epoll_ctl(EpollFds[0][0], EPOLL_CTL_ADD, EpollFds[EPOLL_CHAIN_COUNT - 1][Index - 1], &EpollControlEvent), ELOOP);
3320
3321 //
3322 // The resulting chain is essentially useless. Try to add a file descriptor
3323 // to a node in the chain.
3324 //
3325
3326 LxtCheckErrnoFailure(epoll_ctl(EpollFds[0][0], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent), EINVAL);
3327
3328 LxtCheckErrnoFailure(epoll_ctl(EpollFds[EPOLL_CHAIN_COUNT - 1][0], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent), EINVAL);
3329
3330 LxtCheckErrno(epoll_ctl(EpollFds[EPOLL_CHAIN_COUNT - 1][1], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
3331
3332 LxtCheckErrnoFailure(epoll_ctl(EpollFds[EPOLL_CHAIN_COUNT - 1][0], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent), EINVAL);
3333
3334 //
3335 // Verify the same file descriptor can be added to two different epolls
3336 // even when they are linked.
3337 //
3338
3339 LxtCheckErrno(epoll_ctl(EpollFds[EPOLL_CHAIN_COUNT - 1][2], EPOLL_CTL_ADD, PipeFileDescriptors[0], &EpollControlEvent));
3340
3341 //
3342 // Test if the really long chain can be waited on.
3343 //
3344
3345 LxtCheckErrno(epoll_wait(EpollFds[EPOLL_CHAIN_COUNT - 1][Index - 1], &EpollWaitEvent, 1, 0));
3346
3347 LxtCheckEqual(Result, 0, "%d");
3348
3349 LxtCheckErrno(write(PipeFileDescriptors[1], "\n", 1));
3350 LxtCheckErrno(epoll_wait(EpollFds[EPOLL_CHAIN_COUNT - 1][Index - 1], &EpollWaitEvent, 1, -1));
3351
3352 LxtCheckEqual(Result, 1, "%d");
3353
3354 //
3355 // Try removing a node deep in the chain.
3356 //
3357
3358 LxtCheckErrno(epoll_ctl(
3359 EpollFds[EPOLL_CHAIN_COUNT / 2][EPOLL_MAX_RECURSION_COUNT / 2],
3360 EPOLL_CTL_DEL,
3361 EpollFds[EPOLL_CHAIN_COUNT / 2][EPOLL_MAX_RECURSION_COUNT / 2 - 1],
3362 NULL));
3363
3364 ErrorExit:
3365 if (ExtraEpollFd != -1)
3366 {
3367 close(ExtraEpollFd);
3368 }
3369
3370 for (Index = 0; Index < EPOLL_MAX_RECURSION_COUNT; Index += 1)
3371 {
3372 if (EpollContentFds[Index] != -1)
3373 {
3374 close(EpollContentFds[Index]);
3375 }
3376 }
3377
3378 for (ChainIndex = 0; ChainIndex < EPOLL_CHAIN_COUNT; ChainIndex += 1)
3379 {
3380 for (Index = 0; Index < EPOLL_MAX_RECURSION_COUNT; Index += 1)
3381 {
3382 if (EpollFds[ChainIndex][Index] != -1)
3383 {
3384 close(EpollFds[ChainIndex][Index]);
3385 }
3386 }
3387 }
3388
3389 if (PipeFileDescriptors[1] != -1)
3390 {
3391 close(PipeFileDescriptors[1]);
3392 }
3393
3394 if (PipeFileDescriptors[0] != -1)
3395 {
3396 close(PipeFileDescriptors[0]);
3397 }
3398
3399 return Result;
3400 }