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