aboutsummaryrefslogtreecommitdiffstats
path: root/src/common.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/common.h83
1 files changed, 83 insertions, 0 deletions
diff --git a/src/common.h b/src/common.h
index 68d465e..187723e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -47,6 +47,43 @@ static const char *failed__ = NULL;
/**
+ * A queued job.
+ */
+struct job {
+ /**
+ * The job number.
+ */
+ size_t no;
+
+ /**
+ * The number of “argv” elements in `payload`.
+ */
+ int argc;
+
+ /**
+ * The clock in which `ts` is measured.
+ */
+ clockid_t clk;
+
+ /**
+ * The time when the job shall be executed.
+ */
+ struct timespec ts;
+
+ /**
+ * The number of bytes in `payload`.
+ */
+ size_t n;
+
+ /**
+ * “argv” followed by “envp”.
+ */
+ char payload[];
+};
+
+
+
+/**
* Defines the function `void usage(void)`
* that prints usage information.
*
@@ -132,3 +169,49 @@ fail: \
free(msg); \
return 1;
+
+/**
+ * This block of code allows us to compile with DEBUG=valgrind
+ * or DEBUG=strace and have all exec:s be wrapped in
+ * valgrind --leak-check=full --show-leak-kinds=all or
+ * strace, respectively. Very useful for debugging. However,
+ * children do not inherit strace, so between forking and
+ * exec:ing we do not have strace.
+ */
+#if 1 && defined(DEBUG)
+# if ((DEBUG == 2) || (DEBUG == 3))
+# ifdef __GNUC__
+# pragma GCC diagnostic push
+# pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
+__attribute__((__used__))
+# endif
+# if DEBUG == 2
+# define DEBUGPROG "strace"
+# else
+# define DEBUGPROG "valgrind"
+# endif
+# define execl(path, _, ...) (execl)("/usr/bin/" DEBUGPROG, "/usr/bin/" DEBUGPROG, path, __VA_ARGS__)
+# define execve(...) execve_(__VA_ARGS__)
+static int
+execve_(const char *path, char *const argv[], char *const envp[])
+{
+ size_t n = 0;
+ char **new_argv = NULL;
+ int x = (DEBUG - 2) * 2, saved_errno;
+ while (argv[n++]);
+ t (!(new_argv = malloc((n + 1 + (size_t)x) * sizeof(char *))));
+ new_argv[x] = "--show-leak-kinds=all";
+ new_argv[1] = "--leak-check=full";
+ new_argv[0] = "/usr/bin/" DEBUGPROG;
+ new_argv[1 + x] = path;
+ memcpy(new_argv + 2 + x, argv + 1, (n - 1) * sizeof(char *));
+ (execve)(*new_argv, new_argv, envp);
+fail:
+ return saved_errno = errno, free(new_argv), errno = saved_errno, -1;
+}
+# ifdef __GNUC__
+# pragma GCC diagnostic pop
+# endif
+# endif
+#endif
+