Fix run-read_all and fix hang if they should fail.
[ccan] / ccan / read_write_all / test / run-read_all.c
1 /* FIXME: Do something tricky to ensure we really do loop in read_all. */
2
3 #include "read_write_all/read_write_all.h"
4 #include "read_write_all/read_write_all.c"
5 #include "tap/tap.h"
6 #include <unistd.h>
7 #include <sys/types.h>
8 #include <signal.h>
9 #include <sys/wait.h>
10 #include <limits.h>
11 #include <err.h>
12 #include <stdlib.h>
13 #include <string.h>
14
15 static volatile int sigcount;
16 static int p2c[2], c2p[2];
17 static void got_signal(int sig)
18 {
19         char c = 0;
20         if (write(p2c[1], &c, 1) == 1)
21                 sigcount++;
22 }
23
24 /* < PIPE_BUF *will* be atomic.  But > PIPE_BUF only *might* be non-atomic. */
25 #define BUFSZ (1024*1024)
26
27 int main(int argc, char *argv[])
28 {
29         char buffer[BUFSZ*2] = { 0 };
30         char c = 0;
31         int status;
32         pid_t child;
33
34         plan_tests(6);
35
36         /* We fork and torture parent. */
37         if (pipe(p2c) != 0 || pipe(c2p) != 0)
38                 err(1, "pipe");
39         child = fork();
40
41         if (!child) {
42                 close(p2c[1]);
43                 close(c2p[0]);
44                 /* Child.  Make sure parent ready, then write in two parts. */
45                 if (read(p2c[0], &c, 1) != 1)
46                         exit(1);
47                 memset(buffer, 0xff, sizeof(buffer));
48                 if (!write_all(c2p[1], buffer, BUFSZ))
49                         exit(2);
50                 if (kill(getppid(), SIGUSR1) != 0)
51                         exit(3);
52                 /* Make sure they get signal. */
53                 if (read(p2c[0], &c, 1) != 1)
54                         exit(4);
55                 if (write(c2p[1], buffer, BUFSZ) != BUFSZ)
56                         exit(5);
57                 exit(0);
58         }
59         if (child == -1)
60                 err(1, "forking");
61
62         close(p2c[0]);
63         close(c2p[1]);
64         signal(SIGUSR1, got_signal);
65         ok1(write(p2c[1], &c, 1) == 1);
66         ok1(read_all(c2p[0], buffer, sizeof(buffer)));
67         ok1(memchr(buffer, 0, sizeof(buffer)) == NULL);
68         ok1(sigcount == 1);
69         ok1(wait(&status) == child);
70         ok(WIFEXITED(status) && WEXITSTATUS(status) == 0,
71            "WIFEXITED(status) = %u, WEXITSTATUS(status) = %u",
72            WIFEXITED(status), WEXITSTATUS(status));
73         return exit_status();
74 }