diff options
author | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-06-28 21:17:29 +0000 |
---|---|---|
committer | ko1 <ko1@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2011-06-28 21:17:29 +0000 |
commit | c22126755cd89f2b8aa309df8908d839e588a3bd (patch) | |
tree | 6a8f60739dffae50ce16a690eda77eaa56cdd550 | |
parent | 58018f1f2d41ec28203439496537106e6b08c377 (diff) | |
download | ruby-c22126755cd89f2b8aa309df8908d839e588a3bd.tar.gz |
* error.c (rb_async_bug_errno): async-safe bug report function.
In timer thread, signal handler shoul use it.
The patch is contributed by Eric Wong <normalperson@yhbt.net>.
Refs: [ruby-core:37644] and [ruby-core:37647]
* thread_pthread.c: use rb_async_bug_errno().
And replace all fprintf() to write().
* internal.h (rb_async_bug_errno): add decl. of above func.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@32274 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | error.c | 46 | ||||
-rw-r--r-- | internal.h | 1 | ||||
-rw-r--r-- | thread_pthread.c | 18 |
4 files changed, 64 insertions, 13 deletions
@@ -1,3 +1,15 @@ +Wed Jun 29 06:09:54 2011 Koichi Sasada <ko1@atdot.net> + + * error.c (rb_async_bug_errno): async-safe bug report function. + In timer thread, signal handler shoul use it. + The patch is contributed by Eric Wong <normalperson@yhbt.net>. + Refs: [ruby-core:37644] and [ruby-core:37647] + + * thread_pthread.c: use rb_async_bug_errno(). + And replace all fprintf() to write(). + + * internal.h (rb_async_bug_errno): add decl. of above func. + Tue Jun 28 23:46:08 2011 Keiju Ishitsuka <keiju@ishitsuka.com> * lib/tracer.rb: count only non-internal libraries in stack trace, @@ -21,6 +21,9 @@ #include <stdlib.h> #endif #include <errno.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif #ifndef EXIT_SUCCESS #define EXIT_SUCCESS 0 @@ -36,6 +39,13 @@ extern const char ruby_description[]; +#define REPORTBUG_MSG \ + "[NOTE]\n" \ + "You may have encountered a bug in the Ruby interpreter" \ + " or extension libraries.\n" \ + "Bug reports are welcome.\n" \ + "For details: http://www.ruby-lang.org/bugreport.html\n\n" \ + static const char * rb_strerrno(int err) { @@ -247,12 +257,7 @@ report_bug(const char *file, int line, const char *fmt, va_list args) rb_vm_bugreport(); - fprintf(out, - "[NOTE]\n" - "You may have encountered a bug in the Ruby interpreter" - " or extension libraries.\n" - "Bug reports are welcome.\n" - "For details: http://www.ruby-lang.org/bugreport.html\n\n"); + fprintf(out, REPORTBUG_MSG); } } @@ -286,6 +291,35 @@ rb_bug_errno(const char *mesg, int errno_arg) } } +/* + * this is safe to call inside signal handler and timer thread + * (which isn't a Ruby Thread object) + */ +#define WRITE_CONST(fd,str) write((fd),(str),sizeof(str) - 1) + +void rb_async_bug_errno(const char *mesg, int errno_arg) +{ + WRITE_CONST(2, "[ASYNC BUG] "); + write(2, mesg, strlen(mesg)); + WRITE_CONST(2, "\n"); + + if (errno_arg == 0) { + WRITE_CONST(2, "errno == 0 (NOERROR)\n"); + } + else { + const char *errno_str = rb_strerrno(errno_arg); + + if (!errno_str) + errno_str = "undefined errno"; + write(2, errno_str, strlen(errno_str)); + } + WRITE_CONST(2, "\n\n"); + write(2, ruby_description, strlen(ruby_description)); + WRITE_CONST(2, "\n\n"); + WRITE_CONST(2, REPORTBUG_MSG); + abort(); +} + void rb_compile_bug(const char *file, int line, const char *fmt, ...) { diff --git a/internal.h b/internal.h index 350504646d..ec61b32ae7 100644 --- a/internal.h +++ b/internal.h @@ -76,6 +76,7 @@ void rb_gc_mark_encodings(void); /* error.c */ NORETURN(PRINTF_ARGS(void rb_compile_bug(const char*, int, const char*, ...), 3, 4)); VALUE rb_check_backtrace(VALUE); +NORETURN(void rb_async_bug_errno(const char *,int)); /* eval_error.c */ void ruby_error_print(void); diff --git a/thread_pthread.c b/thread_pthread.c index e78c10fb46..420a3f4db5 100644 --- a/thread_pthread.c +++ b/thread_pthread.c @@ -990,6 +990,9 @@ static int timer_thread_pipe_owner_process; #define TT_DEBUG 0 +#define WRITE_CONST(fd, str) write((fd),(str),sizeof(str)-1); + +/* only use signal-safe system calls here */ void rb_thread_wakeup_timer_thread(void) { @@ -1008,16 +1011,17 @@ rb_thread_wakeup_timer_thread(void) #endif break; default: - rb_bug_errno("rb_thread_wakeup_timer_thread - write", errno); + rb_async_bug_errno("rb_thread_wakeup_timer_thread - write", errno); } } - if (TT_DEBUG) fprintf(stderr, "rb_thread_wakeup_timer_thread: write\n"); + if (TT_DEBUG) WRITE_CONST(2, "rb_thread_wakeup_timer_thread: write\n"); } else { /* ignore wakeup */ } } +/* VM-dependent API is not available for this function */ static void consume_communication_pipe(void) { @@ -1032,7 +1036,7 @@ consume_communication_pipe(void) switch (errno) { case EINTR: goto retry; default: - rb_bug_errno("consume_communication_pipe: read", errno); + rb_async_bug_errno("consume_communication_pipe: read\n", errno); } } } @@ -1061,7 +1065,7 @@ thread_timer(void *p) int result; struct timeval timeout; - if (TT_DEBUG) fprintf(stderr, "start timer thread\n"); + if (TT_DEBUG) WRITE_CONST(2, "start timer thread\n"); while (system_working > 0) { fd_set rfds; @@ -1069,7 +1073,7 @@ thread_timer(void *p) /* timer function */ ping_signal_thread_list(); timer_thread_function(0); - if (TT_DEBUG) fprintf(stderr, "tick\n"); + if (TT_DEBUG) WRITE_CONST(2, "tick\n"); /* wait */ FD_ZERO(&rfds); @@ -1098,12 +1102,12 @@ thread_timer(void *p) /* interrupted. ignore */ } else { - rb_bug_errno("thread_timer: select", errno); + rb_async_bug_errno("thread_timer: select", errno); } } } - if (TT_DEBUG) fprintf(stderr, "finish timer thread\n"); + if (TT_DEBUG) WRITE_CONST(2, "finish timer thread\n"); return NULL; } |