1 /* 2 * Rudimentary test suite used while implementing pselect(2). 3 */ 4 5 #include <assert.h> 6 #include <errno.h> 7 #include <signal.h> 8 #include <stdio.h> 9 #include <string.h> 10 #include <unistd.h> 11 12 13 static int alarm_flag = 0; 14 15 16 static void 17 nop(int signo) 18 { 19 } 20 21 22 static void 23 set_alarm_flag(int signo) 24 { 25 alarm_flag = 1; 26 } 27 28 29 30 /* 31 * Very roughly exercise pselect(2). 32 */ 33 34 static void 35 test_pselect() 36 { 37 fd_set rset; 38 fd_set wset; 39 sigset_t blockset; 40 struct timespec timeout; 41 int des[2]; 42 int r; 43 char buf[1]; 44 45 printf("test_pselect\n"); 46 47 /* 48 * It is always possible to write to stdout (if not redirected). 49 */ 50 51 FD_ZERO(&wset); 52 FD_SET(1, &wset); 53 54 r = pselect(2, NULL, &wset, NULL, NULL, NULL); 55 assert(r == 1); 56 assert(FD_ISSET(1, &wset)); 57 58 /* 59 * Write to a pipe and check a select on the read end does not block. 60 */ 61 62 r = pipe(des); 63 assert(r == 0); 64 65 FD_ZERO(&rset); 66 FD_SET(des[0], &rset); 67 68 buf[0] = 'f'; 69 r = write(des[1], buf, 1); 70 assert(r == 1); 71 72 r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL); 73 assert(r == 1); 74 assert(FD_ISSET(des[0], &rset)); 75 76 r = read(des[0], buf, 1); 77 assert(r == 1); 78 assert(buf[0] == 'f'); 79 80 /* 81 * Block until signal reception. 82 */ 83 84 signal(SIGALRM, nop); 85 alarm(1); 86 87 FD_ZERO(&rset); 88 FD_SET(des[0], &rset); 89 90 r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL); 91 assert(r == -1); 92 assert(errno == EINTR); 93 94 /* 95 * Block until timeout. 96 */ 97 98 FD_ZERO(&rset); 99 FD_SET(des[0], &rset); 100 101 timeout.tv_sec = 1; 102 timeout.tv_nsec = 0; 103 r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL); 104 assert(r == 0); 105 106 /* 107 * When the timeout is zero, the call should not block. 108 */ 109 110 timeout.tv_sec = 0; 111 timeout.tv_nsec = 0; 112 FD_ZERO(&rset); 113 FD_SET(des[0], &rset); 114 115 r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL); 116 assert(r == 0); 117 118 /* 119 * When a signal is masked, the syscall is not interrupted and the 120 * signal is received on completion. 121 */ 122 123 sigemptyset(&blockset); 124 sigaddset(&blockset, SIGALRM); 125 126 signal(SIGALRM, set_alarm_flag); 127 alarm(1); 128 129 timeout.tv_sec = 2; 130 timeout.tv_nsec = 0; 131 r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, &blockset); 132 assert(r == 0); 133 assert(alarm_flag); 134 135 close(des[0]); 136 close(des[1]); 137 } 138 139 140 int 141 main(void) 142 { 143 test_pselect(); 144 return (0); 145 } 146