X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ffailtest%2Ffailtest.c;h=dae3024ef97f55c24be4169a6589e7ef01258373;hb=42cdf910d2ab677e8cdafe17085efdf68c12b3da;hp=b394848fad79cb5dc72ac5fc94e119ffae066aa4;hpb=614259f13c3e694fcd6b57fc05a329066e43c76d;p=ccan diff --git a/ccan/failtest/failtest.c b/ccan/failtest/failtest.c index b394848f..dae3024e 100644 --- a/ccan/failtest/failtest.c +++ b/ccan/failtest/failtest.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -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="))) {