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>
18int pip[2];
19
20int pipemax;
21
22int
23process (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
59int
60main (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