]> git.ozlabs.org Git - ccan/blobdiff - ccan/failtest/failtest.c
antithread, failtest: use ccan/err instead of err.h.
[ccan] / ccan / failtest / failtest.c
index b394848fad79cb5dc72ac5fc94e119ffae066aa4..b3ee0337ebd96cfb7fe9a3b7cd3114fe473404c8 100644 (file)
@@ -5,7 +5,6 @@
 #include <stdio.h>
 #include <stdarg.h>
 #include <ctype.h>
-#include <err.h>
 #include <unistd.h>
 #include <poll.h>
 #include <errno.h>
 #include <sys/stat.h>
 #include <sys/time.h>
 #include <sys/mman.h>
+#include <sys/resource.h>
 #include <signal.h>
 #include <assert.h>
+#include <ccan/err/err.h>
 #include <ccan/time/time.h>
 #include <ccan/read_write_all/read_write_all.h>
 #include <ccan/failtest/failtest_proto.h>
@@ -27,9 +28,8 @@
 
 enum failtest_result (*failtest_hook)(struct tlist_calls *);
 
-static int tracefd = -1;
+static FILE *tracef = NULL, *warnf;
 static int traceindent = 0;
-static int warnfd;
 
 unsigned int failtest_timeout_ms = 20000;
 
@@ -195,11 +195,21 @@ static struct failtest_call *add_history_(enum failtest_call_type type,
 static int move_fd_to_high(int fd)
 {
        int i;
+       struct rlimit lim;
+       int max;
 
-       for (i = FD_SETSIZE - 1; i >= 0; i--) {
+       if (getrlimit(RLIMIT_NOFILE, &lim) == 0) {
+               max = lim.rlim_cur;
+               printf("Max is %i\n", max);
+       } else
+               max = FD_SETSIZE;
+
+       for (i = max - 1; i > fd; i--) {
                if (fcntl(i, F_GETFL) == -1 && errno == EBADF) {
-                       if (dup2(fd, i) == -1)
-                               err(1, "Failed to dup fd %i to %i", fd, i);
+                       if (dup2(fd, i) == -1) {
+                               warn("Failed to dup fd %i to %i", fd, i);
+                               continue;
+                       }
                        close(fd);
                        return i;
                }
@@ -245,14 +255,14 @@ static char *failpath_string(void)
        return ret;
 }
 
-static void warn_via_fd(int e, const char *fmt, va_list ap)
+static void do_warn(int e, const char *fmt, va_list ap)
 {
        char *p = failpath_string();
 
-       vdprintf(warnfd, fmt, ap);
+       vfprintf(warnf, fmt, ap);
        if (e != -1)
-               dprintf(warnfd, ": %s", strerror(e));
-       dprintf(warnfd, " [%s]\n", p);
+               fprintf(warnf, ": %s", strerror(e));
+       fprintf(warnf, " [%s]\n", p);
        free(p);
 }
 
@@ -262,7 +272,7 @@ static void fwarn(const char *fmt, ...)
        int e = errno;
 
        va_start(ap, fmt);
-       warn_via_fd(e, fmt, ap);
+       do_warn(e, fmt, ap);
        va_end(ap);
 }
 
@@ -272,7 +282,7 @@ static void fwarnx(const char *fmt, ...)
        va_list ap;
 
        va_start(ap, fmt);
-       warn_via_fd(-1, fmt, ap);
+       do_warn(-1, fmt, ap);
        va_end(ap);
 }
 
@@ -302,17 +312,21 @@ static void PRINTF_FMT(1, 2) trace(const char *fmt, ...)
 {
        va_list ap;
        unsigned int i;
+       char *p;
+       static int idx;
 
-       if (tracefd == -1)
+       if (!tracef)
                return;
 
        for (i = 0; i < traceindent; i++)
-               dprintf(tracefd, "  ");
+               fprintf(tracef, "  ");
 
-       dprintf(tracefd, "%u: ", getpid());
+       p = failpath_string();
+       fprintf(tracef, "%i: %u: %s ", idx++, getpid(), p);
        va_start(ap, fmt);
-       vdprintf(tracefd, fmt, ap);
+       vfprintf(tracef, fmt, ap);
        va_end(ap);
+       free(p);
 }
 
 static pid_t child;
@@ -567,7 +581,7 @@ static void free_everything(void)
 {
        struct failtest_call *i;
 
-       while ((i = tlist_top(&history, struct failtest_call, list)) != NULL)
+       while ((i = tlist_top(&history, list)) != NULL)
                free_call(i);
 
        failtable_clear(&failtable);
@@ -737,39 +751,41 @@ static bool should_fail(struct failtest_call *call)
 
        /* Prevent double-printing (in child and parent) */
        fflush(stdout);
+       fflush(warnf);
+       if (tracef)
+               fflush(tracef);
        child = fork();
        if (child == -1)
                err(1, "forking failed");
 
        if (child == 0) {
                traceindent++;
-               if (tracefd != -1) {
+               if (tracef) {
                        struct timeval diff;
                        const char *p;
                        char *failpath;
                        struct failtest_call *c;
 
-                       c = tlist_tail(&history, struct failtest_call, list);
+                       c = tlist_tail(&history, list);
                        diff = time_sub(time_now(), start);
                        failpath = failpath_string();
-                       trace("%u->%u (%u.%02u): %s (", getppid(), getpid(),
-                             (int)diff.tv_sec, (int)diff.tv_usec / 10000,
-                             failpath);
-                       free(failpath);
                        p = strrchr(c->file, '/');
                        if (p)
-                               trace("%s", p+1);
+                               p++;
                        else
-                               trace("%s", c->file);
-                       trace(":%u)\n", c->line);
+                               p = c->file;
+                       trace("%u->%u (%u.%02u): %s (%s:%u)\n",
+                             getppid(), getpid(),
+                             (int)diff.tv_sec, (int)diff.tv_usec / 10000,
+                             failpath, p, c->line);
+                       free(failpath);
                }
                /* From here on, we have to clean up! */
-               our_history_start = tlist_tail(&history, struct failtest_call,
-                                              list);
+               our_history_start = tlist_tail(&history, list);
                close(control[0]);
                close(output[0]);
                /* Don't swallow stderr if we're tracing. */
-               if (tracefd != -1) {
+               if (!tracef) {
                        dup2(output[1], STDOUT_FILENO);
                        dup2(output[1], STDERR_FILENO);
                        if (output[1] != STDOUT_FILENO
@@ -1161,6 +1177,15 @@ void *failtest_mmap(void *addr, size_t length, int prot, int flags,
        return p->u.mmap.ret;
 }
 
+/* Since OpenBSD can't handle adding args, we use this file and line.
+ * This will make all mmaps look the same, reducing coverage. */
+void *failtest_mmap_noloc(void *addr, size_t length, int prot, int flags,
+                         int fd, off_t offset)
+{
+       return failtest_mmap(addr, length, prot, flags, fd, offset,
+                            __FILE__, __LINE__);
+}
+
 static void cleanup_pipe(struct pipe_call *call, bool restore)
 {
        trace("cleaning up pipe fd=%i%s,%i%s\n",
@@ -1675,12 +1700,12 @@ void failtest_init(int argc, char *argv[])
 
        orig_pid = getpid();
 
-       warnfd = move_fd_to_high(dup(STDERR_FILENO));
+       warnf = fdopen(move_fd_to_high(dup(STDERR_FILENO)), "w");
        for (i = 1; i < argc; i++) {
                if (!strncmp(argv[i], "--failpath=", strlen("--failpath="))) {
                        failpath = argv[i] + strlen("--failpath=");
                } else if (strcmp(argv[i], "--trace") == 0) {
-                       tracefd = warnfd;
+                       tracef = warnf;
                        failtest_timeout_ms = -1;
                } else if (!strncmp(argv[i], "--debugpath=",
                                    strlen("--debugpath="))) {