summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--error.c32
-rw-r--r--ext/-test-/bug_reporter/bug_reporter.c24
-rw-r--r--ext/-test-/bug_reporter/extconf.rb1
-rw-r--r--internal.h3
-rw-r--r--test/-ext-/bug_reporter/test_bug_reporter.rb9
6 files changed, 80 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 34ef80a37c..cff8ffd3ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Wed Oct 16 17:37:17 2013 Koichi Sasada <ko1@atdot.net>
+
+ * error.c, internal.h (rb_bug_reporter_add): add a new C-API.
+ rb_bug_reporter_add() allows to register a function which
+ is called at rb_bug() called.
+
+ * ext/-test-/bug_reporter/bug_reporter.c: add a test for this C-API.
+
+ * ext/-test-/bug_reporter/extconf.rb: ditto.
+
+ * test/-ext-/bug_reporter/test_bug_reporter.rb: ditto.
+
Wed Oct 16 15:14:21 2013 Koichi Sasada <ko1@atdot.net>
* NEWS: add a line into NEWS for last commit.
diff --git a/error.c b/error.c
index 531c607509..7f5f2e0385 100644
--- a/error.c
+++ b/error.c
@@ -264,6 +264,29 @@ rb_warn_m(int argc, VALUE *argv, VALUE exc)
return Qnil;
}
+#define MAX_BUG_REPORTERS 0x100
+
+static struct bug_reporters {
+ void (*func)(FILE *out, void *data);
+ void *data;
+} bug_reporters[MAX_BUG_REPORTERS];
+
+static int bug_reporters_size;
+
+int
+rb_bug_reporter_add(void (*func)(FILE *, void *), void *data)
+{
+ struct bug_reporters *reporter;
+ if (bug_reporters_size >= MAX_BUG_REPORTERS) {
+ rb_bug("rb_bug_reporter_add: overflow");
+ }
+ reporter = &bug_reporters[bug_reporters_size++];
+ reporter->func = func;
+ reporter->data = data;
+
+ return bug_reporters_size;
+}
+
static void
report_bug(const char *file, int line, const char *fmt, va_list args)
{
@@ -281,9 +304,16 @@ report_bug(const char *file, int line, const char *fmt, va_list args)
snprintf(buf, 256, "\n%s\n\n", ruby_description);
fputs(buf, out);
-
rb_vm_bugreport();
+ /* call additional bug reporters */
+ {
+ int i;
+ for (i=0; i<bug_reporters_size; i++) {
+ struct bug_reporters *reporter = &bug_reporters[i];
+ (*reporter->func)(out, reporter->data);
+ }
+ }
fprintf(out, REPORTBUG_MSG);
}
}
diff --git a/ext/-test-/bug_reporter/bug_reporter.c b/ext/-test-/bug_reporter/bug_reporter.c
new file mode 100644
index 0000000000..875c3a4617
--- /dev/null
+++ b/ext/-test-/bug_reporter/bug_reporter.c
@@ -0,0 +1,24 @@
+#include <ruby.h>
+#include <stdio.h>
+
+int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
+
+static void
+sample_bug_reporter(FILE *out, void *ptr)
+{
+ int n = (int)ptr;
+ fprintf(out, "Sample bug reporter: %d\n", n);
+}
+
+static VALUE
+register_sample_bug_reporter(VALUE self, VALUE obj)
+{
+ rb_bug_reporter_add(sample_bug_reporter, NUM2INT(obj));
+ return Qnil;
+}
+
+void
+Init_bug_reporter(void)
+{
+ rb_define_global_function("register_sample_bug_reporter", register_sample_bug_reporter, 1);
+}
diff --git a/ext/-test-/bug_reporter/extconf.rb b/ext/-test-/bug_reporter/extconf.rb
new file mode 100644
index 0000000000..76c1e6ff78
--- /dev/null
+++ b/ext/-test-/bug_reporter/extconf.rb
@@ -0,0 +1 @@
+create_makefile("-test-/bug_reporter/bug_reporter")
diff --git a/internal.h b/internal.h
index 403b91bade..c1890961c3 100644
--- a/internal.h
+++ b/internal.h
@@ -772,6 +772,9 @@ VALUE rb_big2str_gmp(VALUE x, int base);
VALUE rb_str2big_gmp(VALUE arg, int base, int badcheck);
#endif
+/* error.c */
+int rb_bug_reporter_add(void (*func)(FILE *, void *), void *data);
+
/* file.c */
#ifdef __APPLE__
VALUE rb_str_normalize_ospath(const char *ptr, long len);
diff --git a/test/-ext-/bug_reporter/test_bug_reporter.rb b/test/-ext-/bug_reporter/test_bug_reporter.rb
new file mode 100644
index 0000000000..319f3ffe9a
--- /dev/null
+++ b/test/-ext-/bug_reporter/test_bug_reporter.rb
@@ -0,0 +1,9 @@
+require 'test/unit'
+require_relative "../../ruby/envutil"
+
+class TestBugReporter < Test::Unit::TestCase
+ def test_bug_reporter_add
+ expected_stderr = /Sample bug reporter: 12345/
+ assert_in_out_err(["--disable-gems", "-r-test-/bug_reporter/bug_reporter", "-e", "register_sample_bug_reporter(12345); Process.kill :SEGV, $$"], "", [], expected_stderr, nil)
+ end
+end