Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tests/sys/kern/pipe/big_pipe_test.c
39488 views
1
#include <sys/select.h>
2
#include <err.h>
3
#include <errno.h>
4
#include <fcntl.h>
5
#include <stdio.h>
6
#include <stdlib.h>
7
#include <string.h>
8
#include <unistd.h>
9
10
#define BIG_PIPE_SIZE 64*1024 /* From sys/pipe.h */
11
12
/*
13
* Test for the non-blocking big pipe bug (write(2) returning
14
* EAGAIN while select(2) returns the descriptor as ready for write).
15
*/
16
17
static void
18
write_frame(int fd, char *buf, unsigned long buflen)
19
{
20
fd_set wfd;
21
int i;
22
23
while (buflen) {
24
FD_ZERO(&wfd);
25
FD_SET(fd, &wfd);
26
i = select(fd+1, NULL, &wfd, NULL, NULL);
27
if (i < 0)
28
err(1, "select failed");
29
if (i != 1) {
30
errx(1, "select returned unexpected value %d\n", i);
31
exit(1);
32
}
33
i = write(fd, buf, buflen);
34
if (i < 0) {
35
if (errno != EAGAIN)
36
warn("write failed");
37
exit(1);
38
}
39
buf += i;
40
buflen -= i;
41
}
42
}
43
44
int
45
main(void)
46
{
47
/* any value over PIPE_SIZE should do */
48
char buf[BIG_PIPE_SIZE];
49
int i, flags, fd[2];
50
51
if (pipe(fd) < 0)
52
errx(1, "pipe failed");
53
54
flags = fcntl(fd[1], F_GETFL);
55
if (flags == -1 || fcntl(fd[1], F_SETFL, flags|O_NONBLOCK) == -1) {
56
printf("fcntl failed: %s\n", strerror(errno));
57
exit(1);
58
}
59
60
switch (fork()) {
61
case -1:
62
err(1, "fork failed: %s\n", strerror(errno));
63
break;
64
case 0:
65
close(fd[1]);
66
for (;;) {
67
/* Any small size should do */
68
i = read(fd[0], buf, 256);
69
if (i == 0)
70
break;
71
if (i < 0)
72
err(1, "read");
73
}
74
exit(0);
75
default:
76
break;
77
}
78
79
close(fd[0]);
80
memset(buf, 0, sizeof buf);
81
for (i = 0; i < 1000; i++)
82
write_frame(fd[1], buf, sizeof buf);
83
84
printf("ok\n");
85
exit(0);
86
}
87
88