failtest: handle EINTR from poll.
[ccan] / ccan / failtest / failtest.h
index 8aae82b352d007d81e94ba4c64104266107b2e92..4df286241d0ef35f8a271251861ae7d0f2c11ac7 100644 (file)
@@ -1,7 +1,9 @@
 #ifndef CCAN_FAILTEST_H
 #define CCAN_FAILTEST_H
+#include "config.h"
 #include <sys/types.h>
 #include <stdbool.h>
+#include <fcntl.h>
 #include <ccan/compiler/compiler.h>
 
 /**
@@ -35,9 +37,11 @@ enum failtest_call_type {
        FAILTEST_CALLOC,
        FAILTEST_REALLOC,
        FAILTEST_OPEN,
+       FAILTEST_CLOSE,
        FAILTEST_PIPE,
        FAILTEST_READ,
        FAILTEST_WRITE,
+       FAILTEST_FCNTL,
 };
 
 struct calloc_call {
@@ -64,13 +68,19 @@ struct open_call {
        mode_t mode;
 };
 
+struct close_call {
+       int fd;
+};
+
 struct pipe_call {
        int ret;
        int fds[2];
+       bool closed[2];
 };
 
 struct read_call {
        ssize_t ret;
+       off_t off;
        int fd;
        void *buf;
        size_t count;
@@ -81,6 +91,18 @@ struct write_call {
        int fd;
        const void *buf;
        size_t count;
+       off_t off;
+};
+
+struct fcntl_call {
+       int ret;
+       int fd;
+       int cmd;
+       union {
+               struct flock fl;
+               long l;
+               int i;
+       } arg;
 };
 
 /**
@@ -106,42 +128,58 @@ struct failtest_call {
        bool fail;
        /* What we set errno to. */
        int error;
+       /* How do we clean this up? */
+       void (*cleanup)(void *u);
        /* The actual call data. */
        union {
                struct calloc_call calloc;
                struct malloc_call malloc;
                struct realloc_call realloc;
                struct open_call open;
+               struct close_call close;
                struct pipe_call pipe;
                struct read_call read;
                struct write_call write;
+               struct fcntl_call fcntl;
        } u;
 };
 
+enum failtest_result {
+       /* Yes try failing this call. */
+       FAIL_OK,
+       /* No, don't try failing this call. */
+       FAIL_DONT_FAIL,
+       /* Try failing this call but don't go too far down that path. */
+       FAIL_PROBE,
+};
+
 /**
  * failtest_hook - whether a certain call should fail or not.
  * @history: the ordered history of all failtest calls.
  * @num: the number of elements in @history (greater than 0)
  *
  * The default value of this hook is failtest_default_hook(), which returns
- * true (ie. yes, fail the call).
+ * FAIL_OK (ie. yes, fail the call).
  *
  * You can override it, and avoid failing certain calls.  The parameters
  * of the call (but not the return value(s)) will be filled in for the last
  * call.
  *
  * Example:
- *     static bool dont_fail_allocations(struct failtest_call *history,
- *                                       unsigned num)
+ *     static enum failtest_result dont_fail_alloc(struct failtest_call *hist,
+ *                                                 unsigned num)
  *     {
- *             return history[num-1].type != FAILTEST_MALLOC
- *                     && history[num-1].type != FAILTEST_CALLOC
- *                     && history[num-1].type != FAILTEST_REALLOC;
+ *             if (hist[num-1].type == FAILTEST_MALLOC
+ *                     || hist[num-1].type == FAILTEST_CALLOC
+ *                     || hist[num-1].type == FAILTEST_REALLOC)
+ *                     return FAIL_DONT_FAIL;
+ *             return FAIL_OK;
  *     }
  *     ...
- *             failtest_hook = dont_fail_allocations;
+ *             failtest_hook = dont_fail_alloc;
  */
-extern bool (*failtest_hook)(struct failtest_call *history, unsigned num);
+extern enum failtest_result
+(*failtest_hook)(struct failtest_call *history, unsigned num);
 
 /**
  * failtest_exit_check - hook for additional checks on a failed child.
@@ -158,9 +196,6 @@ extern bool (*failtest_hook)(struct failtest_call *history, unsigned num);
 extern bool (*failtest_exit_check)(struct failtest_call *history,
                                   unsigned num);
 
-/* This usually fails the call. */
-bool failtest_default_hook(struct failtest_call *history, unsigned num);
-
 /**
  * failtest_timeout_ms - how long to wait before killing child.
  *