summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2013-05-27 21:53:55 +0930
committerRusty Russell <rusty@rustcorp.com.au>2013-05-27 22:13:30 +0930
commit9552c972f725f70ab024e0c9d0487ff078322fd8 (patch)
tree6a8e9a5618d4148684af2387ed1541791ffda0d5
parent75786a7313a8ac224b7501d5cde841dbda16392e (diff)
breakpoint: new module.
Thanks to Jeremy Kerr for the idea! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
-rw-r--r--Makefile-ccan1
l---------ccan/breakpoint/LICENSE1
-rw-r--r--ccan/breakpoint/_info33
-rw-r--r--ccan/breakpoint/breakpoint.c32
-rw-r--r--ccan/breakpoint/breakpoint.h24
-rw-r--r--ccan/breakpoint/test/run.c17
6 files changed, 108 insertions, 0 deletions
diff --git a/Makefile-ccan b/Makefile-ccan
index 7ae3863a..2d713a68 100644
--- a/Makefile-ccan
+++ b/Makefile-ccan
@@ -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
index 00000000..b7951dab
--- /dev/null
+++ b/ccan/breakpoint/LICENSE
@@ -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
index 00000000..5f5251e6
--- /dev/null
+++ b/ccan/breakpoint/_info
@@ -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
index 00000000..279e29a1
--- /dev/null
+++ b/ccan/breakpoint/breakpoint.c
@@ -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
index 00000000..6283a010
--- /dev/null
+++ b/ccan/breakpoint/breakpoint.h
@@ -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
index 00000000..b36e9c22
--- /dev/null
+++ b/ccan/breakpoint/test/run.c
@@ -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();
+}