tselect.c

nthery, 12/26/2007 06:18 PM

Download (3.6 KB)

 
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
 * Try to detect regressions in select(2).
31
 */
32

    
33
static void
34
test_select()
35
{
36
        fd_set rset;
37
        fd_set wset;
38
        struct timeval timeout;
39
        int des[2];
40
        int r;
41
        char buf[1];
42

    
43
        printf("test_select\n");
44

    
45
        /*
46
         * It is always possible to write to stdout (if not redirected).
47
         */
48

    
49
        FD_ZERO(&wset);
50
        FD_SET(1, &wset);
51

    
52
        r = select(2, NULL, &wset, NULL, NULL);
53
        assert(r == 1);
54
        assert(FD_ISSET(1, &wset));
55

    
56
        /*
57
         * Write to a pipe and check a select on the read end does not block.
58
         */
59

    
60
        r = pipe(des);
61
        assert(r == 0);
62

    
63
        FD_ZERO(&rset);
64
        FD_SET(des[0], &rset);
65

    
66
        buf[0] = 'f';
67
        r = write(des[1], buf, 1);
68
        assert(r == 1);
69

    
70
        r = select(des[0]+1, &rset, NULL, NULL, NULL);
71
        assert(r == 1);
72
        assert(FD_ISSET(des[0], &rset));
73

    
74
        r = read(des[0], buf, 1);
75
        assert(r == 1);
76
        assert(buf[0] == 'f');
77

    
78
        /*
79
         * Block until signal reception.
80
         */
81

    
82
        signal(SIGALRM, nop);
83
        alarm(1);
84

    
85
        FD_ZERO(&rset);
86
        FD_SET(des[0], &rset);
87

    
88
        r = select(des[0]+1, &rset, NULL, NULL, NULL);
89
        assert(r == -1);
90
        assert(errno == EINTR);
91

    
92
        /*
93
         * Block until timeout.
94
         */
95

    
96
        FD_ZERO(&rset);
97
        FD_SET(des[0], &rset);
98

    
99
        timeout.tv_sec = 1;
100
        timeout.tv_usec = 0;
101
        r = select(des[0]+1, &rset, NULL, NULL, &timeout);
102
        assert(r == 0);
103

    
104
        /*
105
         * When the timeout is zero, the call should not block.
106
         */
107

    
108
        timeout.tv_sec = 0;
109
        timeout.tv_usec = 0;
110
        FD_ZERO(&rset);
111
        FD_SET(des[0], &rset);
112

    
113
        r = select(des[0]+1, &rset, NULL, NULL, &timeout);
114
        assert(r == 0);
115

    
116
        close(des[0]);
117
        close(des[1]);
118
}
119

    
120

    
121
/*
122
 * Very roughly exercise pselect(2).
123
 */
124

    
125
static void
126
test_pselect()
127
{
128
        fd_set rset;
129
        fd_set wset;
130
        sigset_t blockset;
131
        struct timespec timeout;
132
        int des[2];
133
        int r;
134
        char buf[1];
135

    
136
        printf("test_pselect\n");
137

    
138
        /*
139
         * It is always possible to write to stdout (if not redirected).
140
         */
141

    
142
        FD_ZERO(&wset);
143
        FD_SET(1, &wset);
144

    
145
        r = pselect(2, NULL, &wset, NULL, NULL, NULL);
146
        assert(r == 1);
147
        assert(FD_ISSET(1, &wset));
148

    
149
        /*
150
         * Write to a pipe and check a select on the read end does not block.
151
         */
152

    
153
        r = pipe(des);
154
        assert(r == 0);
155

    
156
        FD_ZERO(&rset);
157
        FD_SET(des[0], &rset);
158

    
159
        buf[0] = 'f';
160
        r = write(des[1], buf, 1);
161
        assert(r == 1);
162

    
163
        r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
164
        assert(r == 1);
165
        assert(FD_ISSET(des[0], &rset));
166

    
167
        r = read(des[0], buf, 1);
168
        assert(r == 1);
169
        assert(buf[0] == 'f');
170

    
171
        /*
172
         * Block until signal reception.
173
         */
174

    
175
        signal(SIGALRM, nop);
176
        alarm(1);
177

    
178
        FD_ZERO(&rset);
179
        FD_SET(des[0], &rset);
180

    
181
        r = pselect(des[0]+1, &rset, NULL, NULL, NULL, NULL);
182
        assert(r == -1);
183
        assert(errno == EINTR);
184

    
185
        /*
186
         * Block until timeout.
187
         */
188

    
189
        FD_ZERO(&rset);
190
        FD_SET(des[0], &rset);
191

    
192
        timeout.tv_sec = 1;
193
        timeout.tv_nsec = 0;
194
        r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
195
        assert(r == 0);
196

    
197
        /*
198
         * When the timeout is zero, the call should not block.
199
         */
200

    
201
        timeout.tv_sec = 0;
202
        timeout.tv_nsec = 0;
203
        FD_ZERO(&rset);
204
        FD_SET(des[0], &rset);
205

    
206
        r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, NULL);
207
        assert(r == 0);
208

    
209
        /*
210
         * When a signal is masked, the syscall is not interrupted and the
211
         * signal is received on completion.
212
         */
213

    
214
        sigemptyset(&blockset);
215
        sigaddset(&blockset, SIGALRM);
216
        
217
        signal(SIGALRM, set_alarm_flag);
218
        alarm(1);
219

    
220
        timeout.tv_sec = 2;
221
        timeout.tv_nsec = 0;
222
        r = pselect(des[0]+1, &rset, NULL, NULL, &timeout, &blockset);
223
        assert(r == 0);
224
        assert(alarm_flag);
225

    
226
        close(des[0]);
227
        close(des[1]);
228
}
229

    
230

    
231
int
232
main(void)
233
{
234
        test_select();
235
        test_pselect();
236
        return (0);
237
}