|
|
@@ -1,7 +1,4 @@
|
|
|
-/* FIXME: Do something tricky to ensure we really do loop in write_all. */
|
|
|
-
|
|
|
#include <ccan/read_write_all/read_write_all.h>
|
|
|
-#include <ccan/read_write_all/read_write_all.c>
|
|
|
#include <ccan/tap/tap.h>
|
|
|
#include <unistd.h>
|
|
|
#include <sys/types.h>
|
|
|
@@ -13,57 +10,58 @@
|
|
|
#include <string.h>
|
|
|
#include <stdio.h>
|
|
|
|
|
|
-static volatile int sigcount;
|
|
|
-static void got_signal(int sig)
|
|
|
+static ssize_t test_write(int fd, const void *buf, size_t count);
|
|
|
+#define write test_write
|
|
|
+#include <ccan/read_write_all/read_write_all.c>
|
|
|
+#undef write
|
|
|
+
|
|
|
+static ssize_t write_return;
|
|
|
+
|
|
|
+static ssize_t test_write(int fd, const void *buf, size_t count)
|
|
|
{
|
|
|
- sigcount++;
|
|
|
+ if (write_return == 0) {
|
|
|
+ errno = ENOSPC;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (write_return < 0) {
|
|
|
+ errno = -write_return;
|
|
|
+ /* Don't return EINTR more than once! */
|
|
|
+ if (errno == EINTR)
|
|
|
+ write_return = count;
|
|
|
+ return -1;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (write_return < count)
|
|
|
+ return write_return;
|
|
|
+ return count;
|
|
|
}
|
|
|
|
|
|
-/* < PIPE_BUF *will* be atomic. But > PIPE_BUF only *might* be non-atomic. */
|
|
|
-#define BUFSZ (1024*1024)
|
|
|
+#define BUFSZ 1024
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
{
|
|
|
char *buffer;
|
|
|
- int p2c[2];
|
|
|
- int status;
|
|
|
- pid_t child;
|
|
|
|
|
|
- buffer = calloc(BUFSZ, 1);
|
|
|
- plan_tests(4);
|
|
|
+ buffer = malloc(BUFSZ);
|
|
|
+ plan_tests(8);
|
|
|
|
|
|
- /* We fork and torture parent. */
|
|
|
- if (pipe(p2c) != 0)
|
|
|
- err(1, "pipe");
|
|
|
- child = fork();
|
|
|
+ write_return = -ENOSPC;
|
|
|
+ ok1(!write_all(100, buffer, BUFSZ));
|
|
|
+ ok1(errno == ENOSPC);
|
|
|
|
|
|
- if (!child) {
|
|
|
- close(p2c[1]);
|
|
|
- /* Make sure they started writing. */
|
|
|
- if (read(p2c[0], buffer, 1) != 1)
|
|
|
- exit(1);
|
|
|
- if (kill(getppid(), SIGUSR1) != 0)
|
|
|
- exit(2);
|
|
|
- if (!read_all(p2c[0], buffer+1, BUFSZ-1))
|
|
|
- exit(3);
|
|
|
- if (memchr(buffer, 0, BUFSZ)) {
|
|
|
- fprintf(stderr, "buffer has 0 at offset %ti\n",
|
|
|
- memchr(buffer, 0, BUFSZ) - (void *)buffer);
|
|
|
- exit(4);
|
|
|
- }
|
|
|
- exit(0);
|
|
|
- }
|
|
|
- if (child == -1)
|
|
|
- err(1, "forking");
|
|
|
+ write_return = -EINTR;
|
|
|
+ ok1(write_all(100, buffer, BUFSZ));
|
|
|
+ ok1(errno == EINTR);
|
|
|
+
|
|
|
+ write_return = 1;
|
|
|
+ errno = 0;
|
|
|
+ ok1(write_all(100, buffer, BUFSZ));
|
|
|
+ ok1(errno == 0);
|
|
|
+
|
|
|
+ write_return = BUFSZ;
|
|
|
+ ok1(write_all(100, buffer, BUFSZ));
|
|
|
+ ok1(errno == 0);
|
|
|
|
|
|
- close(p2c[0]);
|
|
|
- memset(buffer, 0xff, BUFSZ);
|
|
|
- signal(SIGUSR1, got_signal);
|
|
|
- ok1(write_all(p2c[1], buffer, BUFSZ));
|
|
|
- ok1(sigcount == 1);
|
|
|
- ok1(wait(&status) == child);
|
|
|
- ok(WIFEXITED(status) && WEXITSTATUS(status) == 0,
|
|
|
- "WIFEXITED(status) = %u, WEXITSTATUS(status) = %u",
|
|
|
- WIFEXITED(status), WEXITSTATUS(status));
|
|
|
return exit_status();
|
|
|
}
|