aboutsummaryrefslogtreecommitdiffstats
path: root/src/daemon.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/daemon.h')
-rw-r--r--src/daemon.h47
1 files changed, 47 insertions, 0 deletions
diff --git a/src/daemon.h b/src/daemon.h
index 567e268..980cd64 100644
--- a/src/daemon.h
+++ b/src/daemon.h
@@ -279,3 +279,50 @@ int remove_job(const char *jobno, int runjob);
*/
struct job **get_jobs(void);
+
+
+/**
+ * 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
+