breakpoint: new module.
authorRusty Russell <rusty@rustcorp.com.au>
Mon, 27 May 2013 12:23:55 +0000 (21:53 +0930)
committerRusty Russell <rusty@rustcorp.com.au>
Mon, 27 May 2013 12:43:30 +0000 (22:13 +0930)
Thanks to Jeremy Kerr for the idea!

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Makefile-ccan
ccan/breakpoint/LICENSE [new symlink]
ccan/breakpoint/_info [new file with mode: 0644]
ccan/breakpoint/breakpoint.c [new file with mode: 0644]
ccan/breakpoint/breakpoint.h [new file with mode: 0644]
ccan/breakpoint/test/run.c [new file with mode: 0644]

index 7ae3863a349a513376be5baca39f5310ec1cd0b3..2d713a6898e402e21bd45530cc586b63ca86ca4b 100644 (file)
@@ -34,6 +34,7 @@ MODS_WITH_SRC := antithread \
        avl \
        bdelta \
        block_pool \
+       breakpoint \
        btree \
        ccan_tokenizer \
        charset \
diff --git a/ccan/breakpoint/LICENSE b/ccan/breakpoint/LICENSE
new file mode 120000 (symlink)
index 0000000..b7951da
--- /dev/null
@@ -0,0 +1 @@
+../../licenses/CC0
\ No newline at end of file
diff --git a/ccan/breakpoint/_info b/ccan/breakpoint/_info
new file mode 100644 (file)
index 0000000..5f5251e
--- /dev/null
@@ -0,0 +1,33 @@
+#include <string.h>
+#include "config.h"
+
+/**
+ * breakpoint - break if the program is run under gdb.
+ *
+ * This code allows you to insert breakpoints within a program.  These will
+ * do nothing unless your program is run under GDB.
+ *
+ * License: CC0 (Public domain)
+ *
+ * Example:
+ *     #include <ccan/breakpoint/breakpoint.h>
+ *
+ *     int main(void)
+ *     {
+ *             breakpoint();
+ *             return 0;
+ *     }
+ */
+int main(int argc, char *argv[])
+{
+       /* Expect exactly one argument */
+       if (argc != 2)
+               return 1;
+
+       if (strcmp(argv[1], "depends") == 0) {
+               printf("ccan/compiler\n");
+               return 0;
+       }
+
+       return 1;
+}
diff --git a/ccan/breakpoint/breakpoint.c b/ccan/breakpoint/breakpoint.c
new file mode 100644 (file)
index 0000000..279e29a
--- /dev/null
@@ -0,0 +1,32 @@
+/* CC0 (Public domain) - see LICENSE file for details
+ *
+ * Idea for implementation thanks to stackoverflow.com:
+ *     http://stackoverflow.com/questions/3596781/detect-if-gdb-is-running
+ */
+#include <ccan/breakpoint/breakpoint.h>
+
+bool breakpoint_initialized;
+bool breakpoint_under_debug;
+
+/* This doesn't get called if we're under GDB. */
+static void trap(int signum)
+{
+       breakpoint_initialized = true;
+}
+
+void breakpoint_init(void)
+{
+       struct sigaction old, new;
+
+       new.sa_handler = trap;
+       new.sa_flags = 0;
+       sigemptyset(&new.sa_mask);
+       sigaction(SIGTRAP, &new, &old);
+       kill(getpid(), SIGTRAP);
+       sigaction(SIGTRAP, &old, NULL);
+
+       if (!breakpoint_initialized) {
+               breakpoint_initialized = true;
+               breakpoint_under_debug = true;
+       }
+}
diff --git a/ccan/breakpoint/breakpoint.h b/ccan/breakpoint/breakpoint.h
new file mode 100644 (file)
index 0000000..6283a01
--- /dev/null
@@ -0,0 +1,24 @@
+/* CC0 (Public domain) - see LICENSE file for details */
+#ifndef CCAN_BREAKPOINT_H
+#define CCAN_BREAKPOINT_H
+#include <ccan/compiler/compiler.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdbool.h>
+
+void breakpoint_init(void) COLD;
+extern bool breakpoint_initialized;
+extern bool breakpoint_under_debug;
+
+/**
+ * breakpoint - stop if running under the debugger.
+ */
+static inline void breakpoint(void)
+{
+       if (!breakpoint_initialized)
+               breakpoint_init();
+       if (breakpoint_under_debug)
+               kill(getpid(), SIGTRAP);
+}
+#endif /* CCAN_BREAKPOINT_H */
diff --git a/ccan/breakpoint/test/run.c b/ccan/breakpoint/test/run.c
new file mode 100644 (file)
index 0000000..b36e9c2
--- /dev/null
@@ -0,0 +1,17 @@
+#include <ccan/breakpoint/breakpoint.h>
+#include <ccan/breakpoint/breakpoint.c>
+#include <ccan/tap/tap.h>
+
+int main(void)
+{
+       /* This is how many tests you plan to run */
+       plan_tests(2);
+
+       breakpoint();
+
+       ok1(breakpoint_initialized);
+       ok1(!breakpoint_under_debug);
+
+       /* This exits depending on whether all tests passed */
+       return exit_status();
+}