Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/fifo/fifo_io.c
39562 views
1
/*-
2
* Copyright (c) 2005 Robert N. M. Watson
3
* All rights reserved.
4
*
5
* Redistribution and use in source and binary forms, with or without
6
* modification, are permitted provided that the following conditions
7
* are met:
8
* 1. Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
* 2. Redistributions in binary form must reproduce the above copyright
11
* notice, this list of conditions and the following disclaimer in the
12
* documentation and/or other materials provided with the distribution.
13
*
14
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24
* SUCH DAMAGE.
25
*/
26
27
#include <sys/types.h>
28
#include <sys/event.h>
29
#include <sys/ioctl.h>
30
#include <sys/select.h>
31
#include <sys/stat.h>
32
#include <sys/time.h>
33
34
#include <err.h>
35
#include <errno.h>
36
#include <fcntl.h>
37
#include <limits.h>
38
#include <poll.h>
39
#include <signal.h>
40
#include <stdio.h>
41
#include <stdlib.h>
42
#include <string.h>
43
#include <unistd.h>
44
45
/*
46
* Regression test to exercise POSIX fifo I/O.
47
*
48
* We test a number of aspect of behavior, including:
49
*
50
* - If there's no data to read, then for blocking fifos, we block, and for
51
* non-blocking, we return EAGAIN.
52
*
53
* - If we write ten bytes, ten bytes can be read, and they're the same
54
* bytes, in the same order.
55
*
56
* - If we write two batches of five bytes, we can read the same ten bytes in
57
* one read of ten bytes.
58
*
59
* - If we write ten bytes, we can read the same ten bytes in two reads of
60
* five bytes each.
61
*
62
* - If we over-fill a buffer (by writing 512k, which we take to be a large
63
* number above default buffer sizes), we block if there is no reader.
64
*
65
* - That once 512k (ish) is read from the other end, the blocked writer
66
* wakes up.
67
*
68
* - When a fifo is empty, poll, select, kqueue, and fionread report it is
69
* writable but not readable.
70
*
71
* - When a fifo has data in it, poll, select, and kqueue report that it is
72
* writable.
73
*
74
* - XXX: blocked reader semantics?
75
*
76
* - XXX: event behavior on remote close?
77
*
78
* Although behavior of O_RDWR isn't defined for fifos by POSIX, we expect
79
* "reasonable" behavior, and run some additional tests relating to event
80
* management on O_RDWR fifo descriptors.
81
*/
82
83
#define KQUEUE_MAX_EVENT 8
84
85
/*
86
* All activity occurs within a temporary directory created early in the
87
* test.
88
*/
89
static char temp_dir[PATH_MAX];
90
91
static void __unused
92
atexit_temp_dir(void)
93
{
94
95
rmdir(temp_dir);
96
}
97
98
static void
99
makefifo(const char *fifoname, const char *testname)
100
{
101
102
if (mkfifo(fifoname, 0700) < 0)
103
err(-1, "%s: makefifo: mkfifo: %s", testname, fifoname);
104
}
105
106
static void
107
cleanfifo2(const char *fifoname, int fd1, int fd2)
108
{
109
110
if (fd1 != -1)
111
close(fd1);
112
if (fd2 != -1)
113
close(fd2);
114
(void)unlink(fifoname);
115
}
116
117
static void
118
cleanfifo3(const char *fifoname, int fd1, int fd2, int fd3)
119
{
120
121
if (fd3 != -1)
122
close(fd3);
123
cleanfifo2(fifoname, fd1, fd2);
124
}
125
126
/*
127
* Open two different file descriptors for a fifo: one read, one write. Do
128
* so using non-blocking opens in order to avoid deadlocking the process.
129
*/
130
static int
131
openfifo(const char *fifoname, int *reader_fdp, int *writer_fdp)
132
{
133
int error, fd1, fd2;
134
135
fd1 = open(fifoname, O_RDONLY | O_NONBLOCK);
136
if (fd1 < 0)
137
return (-1);
138
fd2 = open(fifoname, O_WRONLY | O_NONBLOCK);
139
if (fd2 < 0) {
140
error = errno;
141
close(fd1);
142
errno = error;
143
return (-1);
144
}
145
*reader_fdp = fd1;
146
*writer_fdp = fd2;
147
148
return (0);
149
}
150
151
/*
152
* Open one file descriptor for the fifo, supporting both read and write.
153
*/
154
static int
155
openfifo_rw(const char *fifoname, int *fdp)
156
{
157
int fd;
158
159
fd = open(fifoname, O_RDWR);
160
if (fd < 0)
161
return (-1);
162
*fdp = fd;
163
164
return (0);
165
}
166
167
static int
168
set_nonblocking(int fd, const char *testname)
169
{
170
int flags;
171
172
flags = fcntl(fd, F_GETFL);
173
if (flags < 0) {
174
warn("%s: fcntl(fd, F_GETFL)", testname);
175
return(-1);
176
}
177
178
flags |= O_NONBLOCK;
179
180
if (fcntl(fd, F_SETFL, flags) < 0) {
181
warn("%s: fcntl(fd, 0x%x)", testname, flags);
182
return (-1);
183
}
184
185
return (0);
186
}
187
188
static int
189
set_blocking(int fd, const char *testname)
190
{
191
int flags;
192
193
flags = fcntl(fd, F_GETFL);
194
if (flags < 0) {
195
warn("%s: fcntl(fd, F_GETFL)", testname);
196
return(-1);
197
}
198
199
flags &= ~O_NONBLOCK;
200
201
if (fcntl(fd, F_SETFL, flags) < 0) {
202
warn("%s: fcntl(fd, 0x%x)", testname, flags);
203
return (-1);
204
}
205
206
return (0);
207
}
208
209
/*
210
* Drain a file descriptor (fifo) of any readable data. Note: resets the
211
* blocking state.
212
*/
213
static int
214
drain_fd(int fd, const char *testname)
215
{
216
ssize_t len;
217
u_char ch;
218
219
if (set_nonblocking(fd, testname) < 0)
220
return (-1);
221
222
while ((len = read(fd, &ch, sizeof(ch))) > 0);
223
if (len < 0) {
224
switch (errno) {
225
case EAGAIN:
226
return (0);
227
default:
228
warn("%s: drain_fd: read", testname);
229
return (-1);
230
}
231
}
232
warn("%s: drain_fd: read: returned 0 bytes", testname);
233
return (-1);
234
}
235
236
/*
237
* Simple I/O test: write ten integers, and make sure we get back the same
238
* integers in the same order. This assumes a minimum fifo buffer > 10
239
* bytes in order to not block and deadlock.
240
*/
241
static void
242
test_simpleio(void)
243
{
244
int i, reader_fd, writer_fd;
245
u_char buffer[10];
246
ssize_t len;
247
248
makefifo("testfifo", __func__);
249
if (openfifo("testfifo", &reader_fd, &writer_fd)
250
< 0) {
251
warn("test_simpleio: openfifo: testfifo");
252
cleanfifo2("testfifo", -1, -1);
253
exit(-1);
254
}
255
256
for (i = 0; i < 10; i++)
257
buffer[i] = i;
258
259
len = write(writer_fd, (char *)buffer, sizeof(buffer));
260
if (len < 0) {
261
warn("test_simpleio: write");
262
cleanfifo2("testfifo", reader_fd, writer_fd);
263
exit(-1);
264
}
265
if (len != sizeof(buffer)) {
266
warnx("test_simplio: tried %zu but wrote %zd", sizeof(buffer),
267
len);
268
cleanfifo2("testfifo", reader_fd, writer_fd);
269
exit(-1);
270
}
271
272
len = read(reader_fd, (char *)buffer, sizeof(buffer));
273
if (len < 0) {
274
warn("test_simpleio: read");
275
cleanfifo2("testfifo", reader_fd, writer_fd);
276
exit(-1);
277
}
278
if (len != sizeof(buffer)) {
279
warnx("test_simpleio: tried %zu but read %zd", sizeof(buffer),
280
len);
281
cleanfifo2("testfifo", reader_fd, writer_fd);
282
exit(-1);
283
}
284
for (i = 0; i < 10; i++) {
285
if (buffer[i] == i)
286
continue;
287
warnx("test_simpleio: write byte %d as 0x%02x, but read "
288
"0x%02x", i, i, buffer[i]);
289
cleanfifo2("testfifo", reader_fd, writer_fd);
290
exit(-1);
291
}
292
293
cleanfifo2("testfifo", reader_fd, writer_fd);
294
}
295
296
static volatile int alarm_fired;
297
/*
298
* Non-destructive SIGALRM handler.
299
*/
300
static void
301
sigalarm(int signum __unused)
302
{
303
304
alarm_fired = 1;
305
}
306
307
/*
308
* Wrapper function for write, which uses a timer to interrupt any blocking.
309
* Because we can't reliably detect EINTR for blocking I/O, we also track
310
* whether or not our timeout fired.
311
*/
312
static int __unused
313
timed_write(int fd, void *data, size_t len, ssize_t *written_lenp,
314
int timeout, int *timedoutp, const char *testname)
315
{
316
struct sigaction act, oact;
317
ssize_t written_len;
318
int error;
319
320
alarm_fired = 0;
321
bzero(&act, sizeof(oact));
322
act.sa_handler = sigalarm;
323
if (sigaction(SIGALRM, &act, &oact) < 0) {
324
warn("%s: timed_write: sigaction", testname);
325
return (-1);
326
}
327
alarm(timeout);
328
written_len = write(fd, data, len);
329
error = errno;
330
alarm(0);
331
if (sigaction(SIGALRM, &oact, NULL) < 0) {
332
warn("%s: timed_write: sigaction", testname);
333
return (-1);
334
}
335
if (alarm_fired)
336
*timedoutp = 1;
337
else
338
*timedoutp = 0;
339
340
errno = error;
341
if (written_len < 0)
342
return (-1);
343
*written_lenp = written_len;
344
return (0);
345
}
346
347
/*
348
* Wrapper function for read, which uses a timer to interrupt any blocking.
349
* Because we can't reliably detect EINTR for blocking I/O, we also track
350
* whether or not our timeout fired.
351
*/
352
static int
353
timed_read(int fd, void *data, size_t len, ssize_t *read_lenp,
354
int timeout, int *timedoutp, const char *testname)
355
{
356
struct sigaction act, oact;
357
ssize_t read_len;
358
int error;
359
360
alarm_fired = 0;
361
bzero(&act, sizeof(oact));
362
act.sa_handler = sigalarm;
363
if (sigaction(SIGALRM, &act, &oact) < 0) {
364
warn("%s: timed_write: sigaction", testname);
365
return (-1);
366
}
367
alarm(timeout);
368
read_len = read(fd, data, len);
369
error = errno;
370
alarm(0);
371
if (sigaction(SIGALRM, &oact, NULL) < 0) {
372
warn("%s: timed_write: sigaction", testname);
373
return (-1);
374
}
375
if (alarm_fired)
376
*timedoutp = 1;
377
else
378
*timedoutp = 0;
379
380
errno = error;
381
if (read_len < 0)
382
return (-1);
383
*read_lenp = read_len;
384
return (0);
385
}
386
387
/*
388
* This test operates on blocking and non-blocking fifo file descriptors, in
389
* order to determine whether they block at good moments or not. By good we
390
* mean: don't block for non-blocking sockets, and do block for blocking
391
* ones, assuming there isn't I/O buffer to satisfy the request.
392
*
393
* We use a timeout of 5 seconds, concluding that in 5 seconds either all I/O
394
* that can take place will, and that if we reach the end of the timeout,
395
* then blocking has occurred.
396
*
397
* We assume that the buffer size on a fifo is <512K, and as such, that
398
* writing that much data without an active reader will result in blocking.
399
*/
400
static void
401
test_blocking_read_empty(void)
402
{
403
int reader_fd, ret, timedout, writer_fd;
404
ssize_t len;
405
u_char ch;
406
407
makefifo("testfifo", __func__);
408
if (openfifo("testfifo", &reader_fd, &writer_fd)
409
< 0) {
410
warn("test_blocking_read_empty: openfifo: testfifo");
411
cleanfifo2("testfifo", -1, -1);
412
exit(-1);
413
}
414
415
/*
416
* Read one byte from an empty blocking fifo, block as there is no
417
* data.
418
*/
419
if (set_blocking(reader_fd, __func__) < 0) {
420
cleanfifo2("testfifo", reader_fd, writer_fd);
421
exit(-1);
422
}
423
424
ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
425
__func__);
426
if (ret != -1) {
427
warnx("test_blocking_read_empty: timed_read: returned "
428
"success");
429
cleanfifo2("testfifo", reader_fd, writer_fd);
430
exit(-1);
431
}
432
if (errno != EINTR) {
433
warn("test_blocking_read_empty: timed_read");
434
cleanfifo2("testfifo", reader_fd, writer_fd);
435
exit(-1);
436
}
437
438
/*
439
* Read one byte from an empty non-blocking fifo, return EAGAIN as
440
* there is no data.
441
*/
442
if (set_nonblocking(reader_fd, __func__) < 0) {
443
cleanfifo2("testfifo", reader_fd, writer_fd);
444
exit(-1);
445
}
446
447
ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
448
__func__);
449
if (ret != -1) {
450
warnx("test_blocking_read_empty: timed_read: returned "
451
"success");
452
cleanfifo2("testfifo", reader_fd, writer_fd);
453
exit(-1);
454
}
455
if (errno != EAGAIN) {
456
warn("test_blocking_read_empty: timed_read");
457
cleanfifo2("testfifo", reader_fd, writer_fd);
458
exit(-1);
459
}
460
461
cleanfifo2("testfifo", reader_fd, writer_fd);
462
}
463
464
/*
465
* Write one byte to an empty fifo, then try to read one byte and make sure
466
* we don't block in either the write or the read. This tests both for
467
* improper blocking in the send and receive code.
468
*/
469
static void
470
test_blocking_one_byte(void)
471
{
472
int reader_fd, ret, timedout, writer_fd;
473
ssize_t len;
474
u_char ch;
475
476
makefifo("testfifo", __func__);
477
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
478
warn("test_blocking: openfifo: testfifo");
479
cleanfifo2("testfifo", -1, -1);
480
exit(-1);
481
}
482
483
if (set_blocking(writer_fd, __func__) < 0) {
484
cleanfifo2("testfifo", reader_fd, writer_fd);
485
exit(-1);
486
}
487
if (set_blocking(reader_fd, __func__) < 0) {
488
cleanfifo2("testfifo", reader_fd, writer_fd);
489
exit(-1);
490
}
491
492
ch = 0xfe;
493
ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout,
494
__func__);
495
if (ret < 0) {
496
warn("test_blocking_one_byte: timed_write");
497
cleanfifo2("testfifo", reader_fd, writer_fd);
498
exit(-1);
499
}
500
if (len != sizeof(ch)) {
501
warnx("test_blocking_one_byte: timed_write: tried to write "
502
"%zu, wrote %zd", sizeof(ch), len);
503
cleanfifo2("testfifo", reader_fd, writer_fd);
504
exit(-1);
505
}
506
507
ch = 0xab;
508
ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
509
__func__);
510
if (ret < 0) {
511
warn("test_blocking_one_byte: timed_read");
512
cleanfifo2("testfifo", reader_fd, writer_fd);
513
exit(-1);
514
}
515
if (len != sizeof(ch)) {
516
warnx("test_blocking_one_byte: timed_read: wanted %zu, "
517
"read %zd", sizeof(ch), len);
518
cleanfifo2("testfifo", reader_fd, writer_fd);
519
exit(-1);
520
}
521
if (ch != 0xfe) {
522
warnx("test_blocking_one_byte: timed_read: expected to read "
523
"0x%02x, read 0x%02x", 0xfe, ch);
524
cleanfifo2("testfifo", reader_fd, writer_fd);
525
exit(-1);
526
}
527
528
cleanfifo2("testfifo", reader_fd, writer_fd);
529
}
530
531
/*
532
* Write one byte to an empty fifo, then try to read one byte and make sure
533
* we don't get back EAGAIN.
534
*/
535
static void
536
test_nonblocking_one_byte(void)
537
{
538
int reader_fd, ret, timedout, writer_fd;
539
ssize_t len;
540
u_char ch;
541
542
makefifo("testfifo", __func__);
543
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
544
warn("test_nonblocking: openfifo: testfifo");
545
cleanfifo2("testfifo", -1, -1);
546
exit(-1);
547
}
548
549
if (set_nonblocking(reader_fd, __func__) < 0) {
550
cleanfifo2("testfifo", reader_fd, writer_fd);
551
exit(-1);
552
}
553
554
ch = 0xfe;
555
ret = timed_write(writer_fd, &ch, sizeof(ch), &len, 5, &timedout,
556
__func__);
557
if (ret < 0) {
558
warn("test_nonblocking_one_byte: timed_write");
559
cleanfifo2("testfifo", reader_fd, writer_fd);
560
exit(-1);
561
}
562
if (len != sizeof(ch)) {
563
warnx("test_nonblocking_one_byte: timed_write: tried to write "
564
"%zu, wrote %zd", sizeof(ch), len);
565
cleanfifo2("testfifo", reader_fd, writer_fd);
566
exit(-1);
567
}
568
569
ch = 0xab;
570
ret = timed_read(reader_fd, &ch, sizeof(ch), &len, 5, &timedout,
571
__func__);
572
if (ret < 0) {
573
warn("test_nonblocking_one_byte: timed_read");
574
cleanfifo2("testfifo", reader_fd, writer_fd);
575
exit(-1);
576
}
577
if (len != sizeof(ch)) {
578
warnx("test_nonblocking_one_byte: timed_read: wanted %zu, read "
579
"%zd", sizeof(ch), len);
580
cleanfifo2("testfifo", reader_fd, writer_fd);
581
exit(-1);
582
}
583
if (ch != 0xfe) {
584
warnx("test_nonblocking_one_byte: timed_read: expected to read "
585
"0x%02x, read 0x%02x", 0xfe, ch);
586
cleanfifo2("testfifo", reader_fd, writer_fd);
587
exit(-1);
588
}
589
590
cleanfifo2("testfifo", reader_fd, writer_fd);
591
}
592
593
/*
594
* First of two test cases involving a 512K buffer: write the buffer into a
595
* blocking file descriptor. We'd like to know it blocks, but the closest we
596
* can get is to see if SIGALRM fired during the I/O resulting in a partial
597
* write.
598
*/
599
static void
600
test_blocking_partial_write(void)
601
{
602
int reader_fd, ret, timedout, writer_fd;
603
u_char *buffer;
604
ssize_t len;
605
606
makefifo("testfifo", __func__);
607
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
608
warn("test_blocking_partial_write: openfifo: testfifo");
609
cleanfifo2("testfifo", -1, -1);
610
exit(-1);
611
}
612
613
if (set_blocking(writer_fd, __func__) < 0) {
614
cleanfifo2("testfifo", reader_fd, writer_fd);
615
exit(-1);
616
}
617
618
buffer = malloc(512*1024);
619
if (buffer == NULL) {
620
warn("test_blocking_partial_write: malloc");
621
cleanfifo2("testfifo", reader_fd, writer_fd);
622
exit(-1);
623
}
624
bzero(buffer, 512*1024);
625
626
ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
627
__func__);
628
if (ret < 0) {
629
warn("test_blocking_partial_write: timed_write");
630
free(buffer);
631
cleanfifo2("testfifo", reader_fd, writer_fd);
632
exit(-1);
633
}
634
635
if (!timedout) {
636
warnx("test_blocking_partial_write: timed_write: blocking "
637
"socket didn't time out");
638
free(buffer);
639
cleanfifo2("testfifo", reader_fd, writer_fd);
640
exit(-1);
641
}
642
643
free(buffer);
644
645
if (drain_fd(reader_fd, __func__) < 0) {
646
cleanfifo2("testfifo", reader_fd, writer_fd);
647
exit(-1);
648
}
649
650
cleanfifo2("testfifo", reader_fd, writer_fd);
651
}
652
653
/*
654
* Write a 512K buffer to an empty fifo using a non-blocking file descriptor,
655
* and make sure it doesn't block.
656
*/
657
static void
658
test_nonblocking_partial_write(void)
659
{
660
int reader_fd, ret, timedout, writer_fd;
661
u_char *buffer;
662
ssize_t len;
663
664
makefifo("testfifo", __func__);
665
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
666
warn("test_blocking_partial_write: openfifo: testfifo");
667
cleanfifo2("testfifo", -1, -1);
668
exit(-1);
669
}
670
671
if (set_nonblocking(writer_fd, __func__) < 0) {
672
cleanfifo2("testfifo", reader_fd, writer_fd);
673
exit(-1);
674
}
675
676
buffer = malloc(512*1024);
677
if (buffer == NULL) {
678
warn("test_blocking_partial_write: malloc");
679
cleanfifo2("testfifo", reader_fd, writer_fd);
680
exit(-1);
681
}
682
bzero(buffer, 512*1024);
683
684
ret = timed_write(writer_fd, buffer, 512*1024, &len, 5, &timedout,
685
__func__);
686
if (ret < 0) {
687
warn("test_blocking_partial_write: timed_write");
688
free(buffer);
689
cleanfifo2("testfifo", reader_fd, writer_fd);
690
exit(-1);
691
}
692
693
if (timedout) {
694
warnx("test_blocking_partial_write: timed_write: "
695
"non-blocking socket timed out");
696
free(buffer);
697
cleanfifo2("testfifo", reader_fd, writer_fd);
698
exit(-1);
699
}
700
701
if (len == 0 || len >= 512*1024) {
702
warnx("test_blocking_partial_write: timed_write: requested "
703
"%d, sent %zd", 512*1024, len);
704
free(buffer);
705
cleanfifo2("testfifo", reader_fd, writer_fd);
706
exit(-1);
707
}
708
709
free(buffer);
710
711
if (drain_fd(reader_fd, __func__) < 0) {
712
cleanfifo2("testfifo", reader_fd, writer_fd);
713
exit(-1);
714
}
715
716
cleanfifo2("testfifo", reader_fd, writer_fd);
717
}
718
719
/*
720
* test_coalesce_big_read() verifies that data mingles in the fifo across
721
* message boundaries by performing two small writes, then a bigger read
722
* that should return data from both writes.
723
*/
724
static void
725
test_coalesce_big_read(void)
726
{
727
int i, reader_fd, writer_fd;
728
u_char buffer[10];
729
ssize_t len;
730
731
makefifo("testfifo", __func__);
732
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
733
warn("test_coalesce_big_read: openfifo: testfifo");
734
cleanfifo2("testfifo", -1, -1);
735
exit(-1);
736
}
737
738
/* Write five, write five, read ten. */
739
for (i = 0; i < 10; i++)
740
buffer[i] = i;
741
742
len = write(writer_fd, buffer, 5);
743
if (len < 0) {
744
warn("test_coalesce_big_read: write 5");
745
cleanfifo2("testfifo", reader_fd, writer_fd);
746
exit(-1);
747
}
748
if (len != 5) {
749
warnx("test_coalesce_big_read: write 5 wrote %zd", len);
750
cleanfifo2("testfifo", reader_fd, writer_fd);
751
exit(-1);
752
}
753
754
len = write(writer_fd, buffer + 5, 5);
755
if (len < 0) {
756
warn("test_coalesce_big_read: write 5");
757
cleanfifo2("testfifo", reader_fd, writer_fd);
758
exit(-1);
759
}
760
if (len != 5) {
761
warnx("test_coalesce_big_read: write 5 wrote %zd", len);
762
cleanfifo2("testfifo", reader_fd, writer_fd);
763
exit(-1);
764
}
765
766
len = read(reader_fd, buffer, 10);
767
if (len < 0) {
768
warn("test_coalesce_big_read: read 10");
769
cleanfifo2("testfifo", reader_fd, writer_fd);
770
exit(-1);
771
}
772
if (len != 10) {
773
warnx("test_coalesce_big_read: read 10 read %zd", len);
774
cleanfifo2("testfifo", reader_fd, writer_fd);
775
exit(-1);
776
}
777
778
for (i = 0; i < 10; i++) {
779
if (buffer[i] == i)
780
continue;
781
warnx("test_coalesce_big_read: expected to read 0x%02x, "
782
"read 0x%02x", i, buffer[i]);
783
cleanfifo2("testfifo", reader_fd, writer_fd);
784
exit(-1);
785
}
786
787
cleanfifo2("testfifo", -1, -1);
788
}
789
790
/*
791
* test_coalesce_big_write() verifies that data mingles in the fifo across
792
* message boundaries by performing one big write, then two smaller reads
793
* that should return sequential elements of data from the write.
794
*/
795
static void
796
test_coalesce_big_write(void)
797
{
798
int i, reader_fd, writer_fd;
799
u_char buffer[10];
800
ssize_t len;
801
802
makefifo("testfifo", __func__);
803
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
804
warn("test_coalesce_big_write: openfifo: testfifo");
805
cleanfifo2("testfifo", -1, -1);
806
exit(-1);
807
}
808
809
/* Write ten, read five, read five. */
810
for (i = 0; i < 10; i++)
811
buffer[i] = i;
812
813
len = write(writer_fd, buffer, 10);
814
if (len < 0) {
815
warn("test_coalesce_big_write: write 10");
816
cleanfifo2("testfifo", reader_fd, writer_fd);
817
exit(-1);
818
}
819
if (len != 10) {
820
warnx("test_coalesce_big_write: write 10 wrote %zd", len);
821
cleanfifo2("testfifo", reader_fd, writer_fd);
822
exit(-1);
823
}
824
825
len = read(reader_fd, buffer, 5);
826
if (len < 0) {
827
warn("test_coalesce_big_write: read 5");
828
cleanfifo2("testfifo", reader_fd, writer_fd);
829
exit(-1);
830
}
831
if (len != 5) {
832
warnx("test_coalesce_big_write: read 5 read %zd", len);
833
cleanfifo2("testfifo", reader_fd, writer_fd);
834
exit(-1);
835
}
836
837
len = read(reader_fd, buffer + 5, 5);
838
if (len < 0) {
839
warn("test_coalesce_big_write: read 5");
840
cleanfifo2("testfifo", reader_fd, writer_fd);
841
exit(-1);
842
}
843
if (len != 5) {
844
warnx("test_coalesce_big_write: read 5 read %zd", len);
845
cleanfifo2("testfifo", reader_fd, writer_fd);
846
exit(-1);
847
}
848
849
for (i = 0; i < 10; i++) {
850
if (buffer[i] == i)
851
continue;
852
warnx("test_coalesce_big_write: expected to read 0x%02x, "
853
"read 0x%02x", i, buffer[i]);
854
cleanfifo2("testfifo", reader_fd, writer_fd);
855
exit(-1);
856
}
857
858
cleanfifo2("testfifo", -1, -1);
859
}
860
861
static int
862
poll_status(int fd, int *readable, int *writable, int *exception,
863
const char *testname)
864
{
865
struct pollfd fds[1];
866
867
fds[0].fd = fd;
868
fds[0].events = POLLIN | POLLOUT | POLLERR;
869
fds[0].revents = 0;
870
871
if (poll(fds, 1, 0) < 0) {
872
warn("%s: poll", testname);
873
return (-1);
874
}
875
*readable = (fds[0].revents & POLLIN) ? 1 : 0;
876
*writable = (fds[0].revents & POLLOUT) ? 1 : 0;
877
*exception = (fds[0].revents & POLLERR) ? 1 : 0;
878
return (0);
879
}
880
881
static int
882
select_status(int fd, int *readable, int *writable, int *exception,
883
const char *testname)
884
{
885
struct fd_set readfds, writefds, exceptfds;
886
struct timeval timeout;
887
888
FD_ZERO(&readfds);
889
FD_ZERO(&writefds);
890
FD_ZERO(&exceptfds);
891
FD_SET(fd, &readfds);
892
FD_SET(fd, &writefds);
893
FD_SET(fd, &exceptfds);
894
timeout.tv_sec = 0;
895
timeout.tv_usec = 0;
896
if (select(fd+1, &readfds, &writefds, &exceptfds, &timeout) < 0) {
897
warn("%s: select", testname);
898
return (-1);
899
}
900
*readable = FD_ISSET(fd, &readfds) ? 1 : 0;
901
*writable = FD_ISSET(fd, &writefds) ? 1 : 0;
902
*exception = FD_ISSET(fd, &exceptfds) ? 1 : 0;
903
return (0);
904
}
905
906
/*
907
* Given an existing kqueue, set up read and write event filters for the
908
* passed file descriptor. Typically called once for the read endpoint, and
909
* once for the write endpoint.
910
*/
911
static int
912
kqueue_setup(int kqueue_fd, int fd, const char *testname)
913
{
914
struct kevent kevent_changelist[2];
915
struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp;
916
struct timespec timeout;
917
int i, ret;
918
919
timeout.tv_sec = 0;
920
timeout.tv_nsec = 0;
921
922
bzero(&kevent_changelist, sizeof(kevent_changelist));
923
EV_SET(&kevent_changelist[0], fd, EVFILT_READ, EV_ADD, 0, 0, 0);
924
EV_SET(&kevent_changelist[1], fd, EVFILT_WRITE, EV_ADD, 0, 0, 0);
925
926
bzero(&kevent_eventlist, sizeof(kevent_eventlist));
927
ret = kevent(kqueue_fd, kevent_changelist, 2, kevent_eventlist,
928
KQUEUE_MAX_EVENT, &timeout);
929
if (ret < 0) {
930
warn("%s:%s: kevent initial register", testname, __func__);
931
return (-1);
932
}
933
934
/*
935
* Verify that the events registered alright.
936
*/
937
for (i = 0; i < ret; i++) {
938
kp = &kevent_eventlist[i];
939
if (kp->flags != EV_ERROR)
940
continue;
941
errno = kp->data;
942
warn("%s:%s: kevent register index %d", testname, __func__,
943
i);
944
return (-1);
945
}
946
947
return (0);
948
}
949
950
static int
951
kqueue_status(int kqueue_fd, int fd, int *readable, int *writable,
952
int *exception, const char *testname)
953
{
954
struct kevent kevent_eventlist[KQUEUE_MAX_EVENT], *kp;
955
struct timespec timeout;
956
int i, ret;
957
958
timeout.tv_sec = 0;
959
timeout.tv_nsec = 0;
960
961
ret = kevent(kqueue_fd, NULL, 0, kevent_eventlist, KQUEUE_MAX_EVENT,
962
&timeout);
963
if (ret < 0) {
964
warn("%s: %s: kevent", testname, __func__);
965
return (-1);
966
}
967
968
*readable = *writable = *exception = 0;
969
for (i = 0; i < ret; i++) {
970
kp = &kevent_eventlist[i];
971
if (kp->ident != (u_int)fd)
972
continue;
973
if (kp->filter == EVFILT_READ)
974
*readable = 1;
975
if (kp->filter == EVFILT_WRITE)
976
*writable = 1;
977
}
978
979
return (0);
980
}
981
982
static int
983
fionread_status(int fd, int *readable, const char *testname)
984
{
985
int i;
986
987
if (ioctl(fd, FIONREAD, &i) < 0) {
988
warn("%s: ioctl(FIONREAD)", testname);
989
return (-1);
990
}
991
992
if (i > 0)
993
*readable = 1;
994
else
995
*readable = 0;
996
return (0);
997
}
998
999
#define READABLE 1
1000
#define WRITABLE 1
1001
#define EXCEPTION 1
1002
1003
#define NOT_READABLE 0
1004
#define NOT_WRITABLE 0
1005
#define NOT_EXCEPTION 0
1006
1007
static int
1008
assert_status(int fd, int kqueue_fd, int assert_readable,
1009
int assert_writable, int assert_exception, const char *testname,
1010
const char *conditionname, const char *fdname)
1011
{
1012
int readable, writable, exception;
1013
1014
if (poll_status(fd, &readable, &writable, &exception, testname) < 0)
1015
return (-1);
1016
1017
if (readable != assert_readable || writable != assert_writable ||
1018
exception != assert_exception) {
1019
warnx("%s: %s polls r:%d, w:%d, e:%d on %s", testname,
1020
fdname, readable, writable, exception, conditionname);
1021
return (-1);
1022
}
1023
1024
if (select_status(fd, &readable, &writable, &exception, testname) < 0)
1025
return (-1);
1026
1027
if (readable != assert_readable || writable != assert_writable ||
1028
exception != assert_exception) {
1029
warnx("%s: %s selects r:%d, w:%d, e:%d on %s", testname,
1030
fdname, readable, writable, exception, conditionname);
1031
return (-1);
1032
}
1033
1034
if (kqueue_status(kqueue_fd, fd, &readable, &writable, &exception,
1035
testname) < 0)
1036
return (-1);
1037
1038
if (readable != assert_readable || writable != assert_writable ||
1039
exception != assert_exception) {
1040
warnx("%s: %s kevent r:%d, w:%d, e:%d on %s", testname,
1041
fdname, readable, writable, exception, conditionname);
1042
return (-1);
1043
}
1044
1045
if (fionread_status(fd, &readable, __func__) < 0)
1046
return (-1);
1047
1048
if (readable != assert_readable) {
1049
warnx("%s: %s fionread r:%d on %s", testname, fdname,
1050
readable, conditionname);
1051
return (-1);
1052
}
1053
1054
return (0);
1055
}
1056
1057
/*
1058
* test_events() uses poll(), select(), and kevent() to query the status of
1059
* fifo file descriptors and determine whether they match expected state
1060
* based on earlier semantic tests: specifically, whether or not poll/select/
1061
* kevent will correctly inform on readable/writable state following I/O.
1062
*
1063
* It would be nice to also test status changes as a result of closing of one
1064
* or another fifo endpoint.
1065
*/
1066
static void
1067
test_events_outofbox(void)
1068
{
1069
int kqueue_fd, reader_fd, writer_fd;
1070
1071
makefifo("testfifo", __func__);
1072
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
1073
warn("test_events_outofbox: openfifo: testfifo");
1074
cleanfifo2("testfifo", -1, -1);
1075
exit(-1);
1076
}
1077
1078
kqueue_fd = kqueue();
1079
if (kqueue_fd < 0) {
1080
warn("%s: kqueue", __func__);
1081
cleanfifo2("testfifo", reader_fd, writer_fd);
1082
exit(-1);
1083
}
1084
1085
if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
1086
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1087
exit(-1);
1088
}
1089
1090
if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
1091
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1092
exit(-1);
1093
}
1094
1095
/*
1096
* Make sure that fresh, out-of-the-box fifo file descriptors have
1097
* good initial states. The reader_fd should have no active state,
1098
* since it will not be readable (no data in pipe), writable (it's
1099
* a read-only descriptor), and there's no reason for error yet.
1100
*/
1101
if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
1102
NOT_EXCEPTION, __func__, "create", "reader_fd") < 0) {
1103
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1104
exit(-1);
1105
}
1106
1107
/*
1108
* Make sure that fresh, out-of-the-box fifo file descriptors have
1109
* good initial states. The writer_fd should be ready to write.
1110
*/
1111
if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1112
NOT_EXCEPTION, __func__, "create", "writer_fd") < 0) {
1113
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1114
exit(-1);
1115
}
1116
1117
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1118
}
1119
1120
static void
1121
test_events_write_read_byte(void)
1122
{
1123
int kqueue_fd, reader_fd, writer_fd;
1124
ssize_t len;
1125
u_char ch;
1126
1127
makefifo("testfifo", __func__);
1128
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
1129
warn("test_events_write_read_byte: openfifo: testfifo");
1130
cleanfifo2("testfifo", -1, -1);
1131
exit(-1);
1132
}
1133
1134
kqueue_fd = kqueue();
1135
if (kqueue_fd < 0) {
1136
warn("%s: kqueue", __func__);
1137
cleanfifo2("testfifo", reader_fd, writer_fd);
1138
exit(-1);
1139
}
1140
1141
if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
1142
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1143
exit(-1);
1144
}
1145
1146
if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
1147
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1148
exit(-1);
1149
}
1150
1151
/*
1152
* Write a byte to the fifo, and make sure that the read end becomes
1153
* readable, and that the write end remains writable (small write).
1154
*/
1155
ch = 0x00;
1156
len = write(writer_fd, &ch, sizeof(ch));
1157
if (len < 0) {
1158
warn("%s: write", __func__);
1159
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1160
exit(-1);
1161
}
1162
1163
if (assert_status(reader_fd, kqueue_fd, READABLE, NOT_WRITABLE,
1164
NOT_EXCEPTION, __func__, "write", "reader_fd") < 0) {
1165
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1166
exit(-1);
1167
}
1168
1169
/*
1170
* the writer_fd should remain writable.
1171
*/
1172
if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1173
NOT_EXCEPTION, __func__, "write", "writer_fd") < 0) {
1174
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1175
exit(-1);
1176
}
1177
1178
/*
1179
* Read the byte from the reader_fd, and now confirm that the fifo
1180
* becomes unreadable.
1181
*/
1182
len = read(reader_fd, &ch, sizeof(ch));
1183
if (len < 0) {
1184
warn("%s: read", __func__);
1185
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1186
exit(-1);
1187
}
1188
1189
if (assert_status(reader_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
1190
NOT_EXCEPTION, __func__, "write+read", "reader_fd") < 0) {
1191
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1192
exit(-1);
1193
}
1194
1195
/*
1196
* The writer_fd should remain writable.
1197
*/
1198
if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1199
NOT_EXCEPTION, __func__, "write+read", "writer_fd") < 0) {
1200
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1201
exit(-1);
1202
}
1203
1204
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1205
}
1206
1207
/*
1208
* Write a 512k buffer to the fifo in non-blocking mode, and make sure that
1209
* the write end becomes un-writable as a result of a partial write that
1210
* fills the fifo buffer.
1211
*/
1212
static void
1213
test_events_partial_write(void)
1214
{
1215
int kqueue_fd, reader_fd, writer_fd;
1216
u_char *buffer;
1217
ssize_t len;
1218
1219
makefifo("testfifo", __func__);
1220
if (openfifo("testfifo", &reader_fd, &writer_fd) < 0) {
1221
warn("test_events_partial_write: openfifo: testfifo");
1222
cleanfifo2("testfifo", -1, -1);
1223
exit(-1);
1224
}
1225
1226
kqueue_fd = kqueue();
1227
if (kqueue_fd < 0) {
1228
warn("%s: kqueue", __func__);
1229
cleanfifo2("testfifo", reader_fd, writer_fd);
1230
exit(-1);
1231
}
1232
1233
if (kqueue_setup(kqueue_fd, reader_fd, __func__) < 0) {
1234
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1235
exit(-1);
1236
}
1237
1238
if (kqueue_setup(kqueue_fd, writer_fd, __func__) < 0) {
1239
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1240
exit(-1);
1241
}
1242
1243
if (set_nonblocking(writer_fd, "test_events") < 0) {
1244
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1245
exit(-1);
1246
}
1247
1248
buffer = malloc(512*1024);
1249
if (buffer == NULL) {
1250
warn("test_events_partial_write: malloc");
1251
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1252
exit(-1);
1253
}
1254
bzero(buffer, 512*1024);
1255
1256
len = write(writer_fd, buffer, 512*1024);
1257
if (len < 0) {
1258
warn("test_events_partial_write: write");
1259
free(buffer);
1260
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1261
exit(-1);
1262
}
1263
1264
free(buffer);
1265
1266
if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, NOT_WRITABLE,
1267
NOT_EXCEPTION, __func__, "big write", "writer_fd") < 0) {
1268
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1269
exit(-1);
1270
}
1271
1272
if (drain_fd(reader_fd, "test_events") < 0) {
1273
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1274
exit(-1);
1275
}
1276
1277
/*
1278
* Test that the writer_fd has been restored to writable state after
1279
* draining.
1280
*/
1281
if (assert_status(writer_fd, kqueue_fd, NOT_READABLE, WRITABLE,
1282
NOT_EXCEPTION, __func__, "big write + drain", "writer_fd") < 0) {
1283
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1284
exit(-1);
1285
}
1286
1287
cleanfifo3("testfifo", reader_fd, writer_fd, kqueue_fd);
1288
}
1289
1290
/*
1291
* We don't comprehensively test O_RDWR file descriptors, but do run a couple
1292
* of event tests to make sure that the fifo implementation doesn't mixed up
1293
* status checks. In particular, at least one past FreeBSD bug exists in
1294
* which the FIONREAD test was performed on the wrong socket implementing the
1295
* fifo, resulting in the fifo never returning readable.
1296
*/
1297
static void
1298
test_events_rdwr(void)
1299
{
1300
int fd, kqueue_fd;
1301
ssize_t len;
1302
char ch;
1303
1304
makefifo("testfifo", __func__);
1305
if (openfifo_rw("testfifo", &fd) < 0) {
1306
warn("%s: openfifo_rw: testfifo", __func__);
1307
cleanfifo2("testfifo", -1, -1);
1308
exit(-1);
1309
}
1310
1311
kqueue_fd = kqueue();
1312
if (kqueue_fd < 0) {
1313
warn("%s: kqueue", __func__);
1314
cleanfifo2("testifo", fd, -1);
1315
exit(-1);
1316
}
1317
1318
if (kqueue_setup(kqueue_fd, fd, __func__) < 0) {
1319
cleanfifo2("testfifo", fd, kqueue_fd);
1320
exit(-1);
1321
}
1322
1323
/*
1324
* On first creation, the O_RDWR descriptor should be writable but
1325
* not readable.
1326
*/
1327
if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE,
1328
NOT_EXCEPTION, __func__, "create", "fd") < 0) {
1329
cleanfifo2("testfifo", fd, kqueue_fd);
1330
exit(-1);
1331
}
1332
1333
/*
1334
* Write a byte, which should cause the file descriptor to become
1335
* readable and writable.
1336
*/
1337
ch = 0x00;
1338
len = write(fd, &ch, sizeof(ch));
1339
if (len < 0) {
1340
warn("%s: write", __func__);
1341
cleanfifo2("testfifo", fd, kqueue_fd);
1342
exit(-1);
1343
}
1344
1345
if (assert_status(fd, kqueue_fd, READABLE, WRITABLE, NOT_EXCEPTION,
1346
__func__, "write", "fd") < 0) {
1347
cleanfifo2("testfifo", fd, kqueue_fd);
1348
exit(-1);
1349
}
1350
1351
/*
1352
* Read a byte, which should cause the file descriptor to return to
1353
* simply being writable.
1354
*/
1355
len = read(fd, &ch, sizeof(ch));
1356
if (len < 0) {
1357
warn("%s: read", __func__);
1358
cleanfifo2("testfifo", fd, kqueue_fd);
1359
exit(-1);
1360
}
1361
1362
if (assert_status(fd, kqueue_fd, NOT_READABLE, WRITABLE,
1363
NOT_EXCEPTION, __func__, "write+read", "fd") < 0) {
1364
cleanfifo2("testfifo", fd, kqueue_fd);
1365
exit(-1);
1366
}
1367
1368
cleanfifo2("testfifo", fd, kqueue_fd);
1369
}
1370
1371
int
1372
main(void)
1373
{
1374
1375
strcpy(temp_dir, "fifo_io.XXXXXXXXXXX");
1376
if (mkdtemp(temp_dir) == NULL)
1377
err(-1, "mkdtemp");
1378
atexit(atexit_temp_dir);
1379
1380
if (chdir(temp_dir) < 0)
1381
err(-1, "chdir %s", temp_dir);
1382
1383
test_simpleio();
1384
test_blocking_read_empty();
1385
test_blocking_one_byte();
1386
test_nonblocking_one_byte();
1387
test_blocking_partial_write();
1388
test_nonblocking_partial_write();
1389
test_coalesce_big_read();
1390
test_coalesce_big_write();
1391
test_events_outofbox();
1392
test_events_write_read_byte();
1393
test_events_partial_write();
1394
test_events_rdwr();
1395
1396
return (0);
1397
}
1398
1399