1 /* Check that closing a pipe with a nonempty buffer works.
2 #notarget: cris*-*-elf
3 #output: got: a\ngot: b\nexit: 0\n
4 */
5
6
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <limits.h>
11 #include <unistd.h>
12 #include <sched.h>
13 #include <signal.h>
14 #include <errno.h>
15 #include <sys/types.h>
16 #include <sys/wait.h>
17 #include <string.h>
18 int pip[2];
19
20 int pipemax;
21
22 int
process(void * arg)23 process (void *arg)
24 {
25 char *s = arg;
26 int lots = pipemax + 256;
27 char *buf = malloc (lots);
28 int ret;
29
30 if (buf == NULL)
31 abort ();
32
33 *buf = *s;
34
35 /* The first write should go straight through. */
36 if (write (pip[1], buf, 1) != 1)
37 abort ();
38
39 *buf = s[1];
40
41 /* The second write may or may not be successful for the whole
42 write, but should be successful for at least the pipemax part.
43 As linux/limits.h clamps PIPE_BUF to 4096, but the page size is
44 actually 8k, we can get away with that much. There should be no
45 error, though. Doing this on host shows that for
46 x86_64-unknown-linux-gnu (2.6.14-1.1656_FC4) pipemax * 10 can be
47 successfully written, perhaps for similar reasons. */
48 ret = write (pip[1], buf, lots);
49 if (ret < pipemax)
50 {
51 fprintf (stderr, "ret: %d, %s, %d\n", ret, strerror (errno), pipemax);
52 fflush (0);
53 abort ();
54 }
55
56 return 0;
57 }
58
59 int
main(void)60 main (void)
61 {
62 int retcode;
63 int pid;
64 int st = 0;
65 long stack[16384];
66 char buf[1];
67
68 /* We need to turn this off because we don't want (to have to model) a
69 SIGPIPE resulting from the close. */
70 if (signal (SIGPIPE, SIG_IGN) != SIG_DFL)
71 abort ();
72
73 retcode = pipe (pip);
74
75 if (retcode != 0)
76 {
77 fprintf (stderr, "Bad pipe %d\n", retcode);
78 abort ();
79 }
80
81 #ifdef PIPE_MAX
82 pipemax = PIPE_MAX;
83 #else
84 pipemax = fpathconf (pip[1], _PC_PIPE_BUF);
85 #endif
86
87 if (pipemax <= 0)
88 {
89 fprintf (stderr, "Bad pipemax %d\n", pipemax);
90 abort ();
91 }
92
93 pid = clone (process, (char *) stack + sizeof (stack) - 64,
94 (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND)
95 | SIGCHLD, "ab");
96 if (pid <= 0)
97 {
98 fprintf (stderr, "Bad clone %d\n", pid);
99 abort ();
100 }
101
102 while ((retcode = read (pip[0], buf, 1)) == 0)
103 ;
104
105 if (retcode != 1)
106 {
107 fprintf (stderr, "Bad read 1: %d\n", retcode);
108 abort ();
109 }
110
111 printf ("got: %c\n", buf[0]);
112
113 /* Need to read out something from the second write too before
114 closing, or the writer can get EPIPE. */
115 while ((retcode = read (pip[0], buf, 1)) == 0)
116 ;
117
118 if (retcode != 1)
119 {
120 fprintf (stderr, "Bad read 2: %d\n", retcode);
121 abort ();
122 }
123
124 printf ("got: %c\n", buf[0]);
125
126 if (close (pip[0]) != 0)
127 {
128 perror ("pip close");
129 abort ();
130 }
131
132 retcode = waitpid (pid, &st, __WALL);
133
134 if (retcode != pid || !WIFEXITED (st))
135 {
136 fprintf (stderr, "Bad wait %d:%d %x\n", pid, retcode, st);
137 perror ("errno");
138 abort ();
139 }
140
141 printf ("exit: %d\n", WEXITSTATUS (st));
142 return 0;
143 }
144