X-Git-Url: http://git.ozlabs.org/?a=blobdiff_plain;f=ccan%2Ffailtest%2Ffailtest.c;h=91420dc699b9c7fdf7f40171b1e39d5fbb7d7ef3;hb=13f96138f7887a97c76582340536478ad5079814;hp=b25b049edac1d162c663ae58218c75dc3815e0dd;hpb=3ad57bc902f31ba347df59de04168f00c626d924;p=ccan diff --git a/ccan/failtest/failtest.c b/ccan/failtest/failtest.c index b25b049e..91420dc6 100644 --- a/ccan/failtest/failtest.c +++ b/ccan/failtest/failtest.c @@ -1,3 +1,4 @@ +/* Licensed under LGPL - see LICENSE file for details */ #include "config.h" #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -57,6 +59,8 @@ static pid_t lock_owner; static struct lock_info *locks = NULL; static unsigned int lock_num = 0; +static pid_t orig_pid; + static const char info_to_arg[] = "mceoxprwf"; /* Dummy call used for failtest_undo wrappers. */ @@ -248,7 +252,8 @@ static struct saved_file *save_file(struct saved_file *next, int fd) s->len = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); s->contents = malloc(s->len); - read(fd, s->contents, s->len); + if (read(fd, s->contents, s->len) != s->len) + err(1, "Failed to save %zu bytes", (size_t)s->len); lseek(fd, s->off, SEEK_SET); return s; } @@ -293,8 +298,11 @@ static void restore_files(struct saved_file *s) struct saved_file *next = s->next; lseek(s->fd, 0, SEEK_SET); - write(s->fd, s->contents, s->len); - ftruncate(s->fd, s->len); + if (write(s->fd, s->contents, s->len) != s->len) + err(1, "Failed to restore %zu bytes", (size_t)s->len); + if (ftruncate(s->fd, s->len) != 0) + err(1, "Failed to trim file to length %zu", + (size_t)s->len); free(s->contents); lseek(s->fd, s->off, SEEK_SET); free(s); @@ -354,7 +362,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) @@ -395,8 +403,8 @@ static bool should_fail(struct failtest_call *call) signal(SIGUSR1, SIG_IGN); sprintf(str, "xterm -e gdb /proc/%d/exe %d &", getpid(), getpid()); - system(str); - sleep(5); + if (system(str) == 0) + sleep(5); } } @@ -404,17 +412,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(); } @@ -672,7 +685,7 @@ int failtest_open(const char *pathname, va_start(ap, line); call.flags = va_arg(ap, int); if (call.flags & O_CREAT) { - call.mode = va_arg(ap, mode_t); + call.mode = va_arg(ap, int); va_end(ap); } p = add_history(FAILTEST_OPEN, file, line, &call); @@ -1019,10 +1032,19 @@ int failtest_fcntl(int fd, const char *file, unsigned line, int cmd, ...) return p->u.fcntl.ret; } +pid_t failtest_getpid(const char *file, unsigned line) +{ + /* You must call failtest_init first! */ + assert(orig_pid); + return orig_pid; +} + void failtest_init(int argc, char *argv[]) { unsigned int i; + orig_pid = getpid(); + for (i = 1; i < argc; i++) { if (!strncmp(argv[i], "--failpath=", strlen("--failpath="))) { failpath = argv[i] + strlen("--failpath="); @@ -1037,6 +1059,11 @@ void failtest_init(int argc, char *argv[]) gettimeofday(&start, NULL); } +bool failtest_has_failed(void) +{ + return control_fd != -1; +} + void failtest_exit(int status) { if (failtest_exit_check) {