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