X-Git-Url: https://git.ozlabs.org/?p=ccan;a=blobdiff_plain;f=ccan%2Ffailtest%2Ffailtest.c;h=c95a94f8d0ce4968dfe9266a47a68343c96b2fa9;hp=d9a0849daf600d1518514df57b74c71be1b78709;hb=407057edd6b45cae437d119df80ff080989a2752;hpb=74257cee33ae3033f961d5f22a0313b8cb1b18d4 diff --git a/ccan/failtest/failtest.c b/ccan/failtest/failtest.c index d9a0849d..c95a94f8 100644 --- a/ccan/failtest/failtest.c +++ b/ccan/failtest/failtest.c @@ -1,5 +1,5 @@ /* Licensed under LGPL - see LICENSE file for details */ -#include "config.h" +#include #include #include #include @@ -15,9 +15,9 @@ #include #include #include +#include #include #include -#include #include enum failtest_result (*failtest_hook)(struct failtest_call *, unsigned); @@ -310,6 +310,16 @@ static void restore_files(struct saved_file *s) } } +static void free_files(struct saved_file *s) +{ + while (s) { + struct saved_file *next = s->next; + free(s->contents); + free(s); + s = next; + } +} + /* Free up memory, so valgrind doesn't report leaks. */ static void free_everything(void) { @@ -362,7 +372,7 @@ static bool should_fail(struct failtest_call *call) struct saved_file *files; /* Are we probing? */ - if (probe_count && --probe_count == 0) + if (probe_count && --probe_count == 0 && control_fd != -1) failtest_cleanup(true, 0); if (call == &unrecorded_call) @@ -412,17 +422,22 @@ static bool should_fail(struct failtest_call *call) switch (failtest_hook(history, history_num)) { case FAIL_OK: break; + case FAIL_PROBE: + /* Already down probe path? Stop now. */ + if (!probe_count) { + /* FIXME: We should run *parent* and + * run probe until calls match up again. */ + probe_count = 3; + break; + } else { + /* Child should give up now. */ + if (control_fd != -1) + failtest_cleanup(true, 0); + /* Parent, don't fail again. */ + } case FAIL_DONT_FAIL: call->fail = false; return false; - case FAIL_PROBE: - /* Already down probe path? Stop now. */ - if (probe_count) - failtest_cleanup(true, 0); - /* FIXME: We should run *parent* and run probe until - * calls match up again. */ - probe_count = 3; - break; default: abort(); } @@ -443,18 +458,13 @@ static bool should_fail(struct failtest_call *call) if (child == 0) { if (tracefd != -1) { - struct timeval now; + struct timeval diff; const char *p; - gettimeofday(&now, NULL); - if (now.tv_usec < start.tv_usec) { - now.tv_sec--; - now.tv_usec += 1000000; - } - now.tv_usec -= start.tv_usec; - now.tv_sec -= start.tv_sec; + + diff = time_sub(time_now(), start); p = failpath_string(); trace("%u->%u (%u.%02u): %s (", getppid(), getpid(), - (int)now.tv_sec, (int)now.tv_usec / 10000, p); + (int)diff.tv_sec, (int)diff.tv_usec / 10000, p); free((char *)p); p = strrchr(history[history_num-1].file, '/'); if (p) @@ -470,6 +480,8 @@ static bool should_fail(struct failtest_call *call) if (output[1] != STDOUT_FILENO && output[1] != STDERR_FILENO) close(output[1]); control_fd = control[1]; + /* Valgrind spots the leak if we don't free these. */ + free_files(files); return true; } @@ -591,14 +603,14 @@ void *failtest_malloc(size_t size, const char *file, unsigned line) p = add_history(FAILTEST_MALLOC, file, line, &call); if (should_fail(p)) { - p->u.calloc.ret = NULL; + p->u.malloc.ret = NULL; p->error = ENOMEM; } else { - p->u.calloc.ret = malloc(size); + p->u.malloc.ret = malloc(size); set_cleanup(p, cleanup_malloc, struct malloc_call); } errno = p->error; - return p->u.calloc.ret; + return p->u.malloc.ret; } static void cleanup_realloc(struct realloc_call *call) @@ -689,7 +701,7 @@ int failtest_open(const char *pathname, free((char *)call.pathname); p->u.open.ret = open(pathname, call.flags, call.mode); - if (!failpath && p->u.open.ret == -1) { + if (p->u.open.ret == -1) { p->fail = false; p->error = errno; } else if (should_fail(p)) { @@ -1051,7 +1063,7 @@ void failtest_init(int argc, char *argv[]) debugpath = argv[i] + strlen("--debugpath="); } } - gettimeofday(&start, NULL); + start = time_now(); } bool failtest_has_failed(void)