diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-05-25 03:46:55 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-05-25 03:46:55 +0000 |
commit | 82f4c4d4d7200c77ee93611b96b97a8326429ce9 (patch) | |
tree | 7422f252d161d2cb8158b18d42fa2271778fc770 /error.c | |
parent | c1b5b93b3ff946dd6a13d201e3c3c80d37f651ff (diff) |
report bug with machine regisiters
* error.c (rb_bug_context): new function to report bug with
context.
* vm_dump.c (rb_vm_bugreport): accepts `ucontext_t` argument to
dump machine regisiters. based on [GH-584].
* signal.c (sigbus, sigsegv): dump machine regisiters if available.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46106 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'error.c')
-rw-r--r-- | error.c | 108 |
1 files changed, 76 insertions, 32 deletions
@@ -292,41 +292,78 @@ rb_bug_reporter_add(void (*func)(FILE *, void *), void *data) return 1; } -static void -report_bug(const char *file, int line, const char *fmt, va_list args) +/* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */ +#define REPORT_BUG_BUFSIZ 256 +static FILE * +bug_report_file(const char *file, int line) { - /* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */ - char buf[256]; + char buf[REPORT_BUG_BUFSIZ]; FILE *out = stderr; - int len = err_position_0(buf, 256, file, line); + int len = err_position_0(buf, sizeof(buf), file, line); if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len || (ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) { + return out; + } + return NULL; +} + +static void +bug_report_begin(FILE *out, const char *fmt, va_list args) +{ + char buf[REPORT_BUG_BUFSIZ]; - fputs("[BUG] ", out); - vsnprintf(buf, 256, fmt, args); - fputs(buf, out); - snprintf(buf, 256, "\n%s\n\n", ruby_description); - fputs(buf, out); + fputs("[BUG] ", out); + vsnprintf(buf, sizeof(buf), fmt, args); + fputs(buf, out); + snprintf(buf, sizeof(buf), "\n%s\n\n", ruby_description); + fputs(buf, out); +} - rb_vm_bugreport(); +#define bug_report_begin(out, fmt) do { \ + va_list args; \ + va_start(args, fmt); \ + bug_report_begin(out, fmt, args); \ + va_end(args); \ +} while (0) - /* 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); - } +static void +bug_report_end(FILE *out) +{ + /* 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); } + fprintf(out, REPORTBUG_MSG); +} + +#define report_bug(file, line, fmt, ctx) do { \ + FILE *out = bug_report_file(file, line); \ + if (out) { \ + bug_report_begin(out, fmt); \ + rb_vm_bugreport(ctx); \ + bug_report_end(out); \ + } \ +} while (0) \ + +NORETURN(static void die(void)); +static void +die(void) +{ +#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80 + _set_abort_behavior( 0, _CALL_REPORTFAULT); +#endif + + abort(); } void rb_bug(const char *fmt, ...) { - va_list args; const char *file = NULL; int line = 0; @@ -335,17 +372,28 @@ rb_bug(const char *fmt, ...) line = rb_sourceline(); } - va_start(args, fmt); - report_bug(file, line, fmt, args); - va_end(args); + report_bug(file, line, fmt, NULL); -#if defined(_WIN32) && defined(RUBY_MSVCRT_VERSION) && RUBY_MSVCRT_VERSION >= 80 - _set_abort_behavior( 0, _CALL_REPORTFAULT); -#endif + die(); +} - abort(); +void +rb_bug_context(const void *ctx, const char *fmt, ...) +{ + const char *file = NULL; + int line = 0; + + if (GET_THREAD()) { + file = rb_sourcefile(); + line = rb_sourceline(); + } + + report_bug(file, line, fmt, ctx); + + die(); } + void rb_bug_errno(const char *mesg, int errno_arg) { @@ -394,11 +442,7 @@ rb_async_bug_errno(const char *mesg, int errno_arg) void rb_compile_bug(const char *file, int line, const char *fmt, ...) { - va_list args; - - va_start(args, fmt); - report_bug(file, line, fmt, args); - va_end(args); + report_bug(file, line, fmt, NULL); abort(); } |