diff --git a/ChangeLog b/ChangeLog index 18daf8345f..65c156553b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,32 @@ +Fri Apr 20 02:37:48 2007 Nobuyoshi Nakada + + * eval.c (ruby_cleanup): re-send signal. [ruby-dev:30516] + + * eval_error.h (error_handle): no message when exiting by signal. + + * intern.h (rb_thread_signal_raise, ruby_default_signal): prototypes. + + * signal.c (esignal_init): takes a signal number and an optional + signal name. + + * signal.c (interrupt_init): pass SIGINT always. + + * signal.c (ruby_default_signal): invoke system default signal + handler. + + * signal.c (rb_f_kill): use NUM2PIDT instead of NUM2INT. + + * signal.c (rb_signal_exec, trap): handle SIGTERM. [ruby-dev:30505] + + * thread.c (rb_thread_signal_raise): now takes signal number instead + of signal name. + + * thread.c (rb_thread_signal_exit): since rb_make_exception() calls + #exception method, rb_class_new_instance() is not needed here. + + * yarvcore.h (struct rb_vm_struct), eval_jump.h (terminate_process): + exit_code is no longer stored in VM. + Thu Apr 19 18:37:49 2007 Koichi Sasada * eval.c, node.h, thread.c, yarvcore.[ch], eval_intern.h: diff --git a/eval.c b/eval.c index b72fbe44de..a7f5cbbd0b 100644 --- a/eval.c +++ b/eval.c @@ -153,40 +153,41 @@ ruby_finalize(void) int ruby_cleanup(int ex) { - int state; - volatile VALUE err = GET_THREAD()->errinfo; + int state, i; + volatile VALUE errs[2] = {GET_THREAD()->errinfo, 0}; rb_vm_t *vm = GET_THREAD()->vm; - /* th->errinfo contains a NODE while break'ing */ - if (RTEST(err) && (TYPE(err) != T_NODE) && - rb_obj_is_kind_of(err, rb_eSystemExit)) { - vm->exit_code = NUM2INT(rb_iv_get(err, "status")); - } - else { - vm->exit_code = 0; - } - GET_THREAD()->safe_level = 0; Init_stack((void *)&state); PUSH_THREAD_TAG(); if ((state = EXEC_TAG()) == 0) { - if (GET_THREAD()->errinfo) { - err = GET_THREAD()->errinfo; - } ruby_finalize_0(); } else if (ex == 0) { ex = state; } + errs[1] = GET_THREAD()->errinfo; rb_thread_terminate_all(); - GET_THREAD()->errinfo = err; + GET_THREAD()->errinfo = errs[0]; ex = error_handle(ex); ruby_finalize_1(); POP_THREAD_TAG(); + rb_thread_stop_timer_thread(); - if (vm->exit_code) { - return vm->exit_code; + for (i = 2; i > 0; --i) { + VALUE err = errs[i]; + + /* th->errinfo contains a NODE while break'ing */ + if (!RTEST(err) || (TYPE(err) == T_NODE)) continue; + + if (rb_obj_is_kind_of(err, rb_eSystemExit)) { + return sysexit_status(err); + } + else if (rb_obj_is_kind_of(err, rb_eSignal)) { + ruby_default_signal(NUM2INT(rb_iv_get(err, "signo"))); + } } + return ex; } diff --git a/eval_error.h b/eval_error.h index 38e85a1d38..155986e836 100644 --- a/eval_error.h +++ b/eval_error.h @@ -233,14 +233,19 @@ error_handle(int ex) warn_printf(": unexpected throw\n"); break; case TAG_RAISE: - case TAG_FATAL: - if (rb_obj_is_kind_of(GET_THREAD()->errinfo, rb_eSystemExit)) { - status = sysexit_status(GET_THREAD()->errinfo); + case TAG_FATAL: { + VALUE errinfo = GET_THREAD()->errinfo; + if (rb_obj_is_kind_of(errinfo, rb_eSystemExit)) { + status = sysexit_status(errinfo); + } + else if (rb_obj_is_instance_of(errinfo, rb_eSignal)) { + /* no message when exiting by signal */ } else { error_print(); } break; + } default: rb_bug("Unknown longjmp status %d", ex); break; diff --git a/eval_jump.h b/eval_jump.h index aa2d84a3fe..485723ecb1 100644 --- a/eval_jump.h +++ b/eval_jump.h @@ -143,7 +143,6 @@ terminate_process(int status, const char *mesg, long mlen) args[0] = INT2NUM(status); args[1] = rb_str_new(mesg, mlen); - vm->exit_code = status; rb_exc_raise(rb_class_new_instance(2, args, rb_eSystemExit)); } diff --git a/intern.h b/intern.h index 1f4c2d3085..c4cd7a7d48 100644 --- a/intern.h +++ b/intern.h @@ -274,7 +274,7 @@ VALUE rb_thread_run(VALUE); VALUE rb_thread_kill(VALUE); VALUE rb_thread_create(VALUE (*)(ANYARGS), void*); void rb_thread_trap_eval(VALUE, int, int); -void rb_thread_signal_raise(void *, const char*); /* should pass literal */ +void rb_thread_signal_raise(void *, int); void rb_thread_signal_exit(void *); int rb_thread_select(int, fd_set *, fd_set *, fd_set *, struct timeval *); void rb_thread_wait_for(struct timeval); @@ -471,6 +471,7 @@ void posix_signal(int, RETSIGTYPE (*)(int)); void rb_trap_exit(void); void rb_trap_exec(void); const char *ruby_signal_name(int); +void ruby_default_signal(int); /* sprintf.c */ VALUE rb_f_sprintf(int, const VALUE*); PRINTF_ARGS(VALUE rb_sprintf(const char*, ...), 1, 2); diff --git a/signal.c b/signal.c index 195939f434..d3810214cc 100644 --- a/signal.c +++ b/signal.c @@ -14,6 +14,8 @@ #include "ruby.h" #include "rubysig.h" +#include "node.h" +#include "yarvcore.h" #include #include @@ -196,6 +198,84 @@ ruby_signal_name(int no) return signo2signm(no); } +/* + * call-seq: + * SignalException.new(sig) => signal_exception + * + * Construct a new SignalException object. +sig+ should be a known + * signal name, or a signal number. + */ + +static VALUE +esignal_init(int argc, VALUE *argv, VALUE self) +{ + int argnum = 1; + VALUE sig = Qnil; + int signo; + const char *signm; + + if (argc > 0) { + sig = rb_check_to_integer(argv[0], "to_int"); + if (!NIL_P(sig)) argnum = 2; + } + if (argc < 1 || argnum < argc) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for %d)", + argc, argnum); + } + if (argnum == 2) { + signo = NUM2INT(sig); + if (signo < 0 || signo > NSIG) { + rb_raise(rb_eArgError, "invalid signal number (%d)", signo); + } + if (argc > 1) { + sig = argv[1]; + } + else { + signm = signo2signm(signo); + if (signm) { + sig = rb_sprintf("SIG%s", signm); + } + else { + sig = rb_sprintf("SIG%u", signo); + } + } + } + else { + signm = SYMBOL_P(sig) ? rb_id2name(SYM2ID(sig)) : StringValuePtr(sig); + if (strncmp(signm, "SIG", 3) == 0) signm += 3; + signo = signm2signo(signm); + if (!signo) { + rb_raise(rb_eArgError, "unsupported name `SIG%s'", signm); + } + if (SYMBOL_P(sig)) { + sig = rb_str_new2(signm); + } + } + rb_call_super(1, &sig); + rb_iv_set(self, "signo", INT2NUM(signo)); + + return self; +} + +static VALUE +interrupt_init(int argc, VALUE *argv, VALUE self) +{ + VALUE args[2]; + + rb_scan_args(argc, argv, "01", &args[1]); + args[0] = INT2FIX(SIGINT); + return rb_call_super(argc + 1, args); +} + +void +ruby_default_signal(int sig) +{ +#ifndef MACOS_UNUSE_SIGNAL + signal(sig, SIG_DFL); + raise(sig); +#endif +} + /* * call-seq: * Process.kill(signal, pid, ...) => fixnum @@ -223,6 +303,9 @@ ruby_signal_name(int no) VALUE rb_f_kill(int argc, VALUE *argv) { +#ifndef HAS_KILLPG +#define killpg(pg, sig) kill(-(pg), sig) +#endif int negative = 0; int sig; int i; @@ -275,22 +358,17 @@ rb_f_kill(int argc, VALUE *argv) if (sig < 0) { sig = -sig; for (i=1; i -#include "yarvcore.h" - static RETSIGTYPE sighandler(int sig) { @@ -498,6 +573,9 @@ rb_signal_exec(rb_thread_t *th, int sig) #ifdef SIGQUIT case SIGQUIT: #endif +#ifdef SIGTERM + case SIGTERM: +#endif #ifdef SIGALRM case SIGALRM: #endif @@ -507,7 +585,7 @@ rb_signal_exec(rb_thread_t *th, int sig) #ifdef SIGUSR2 case SIGUSR2: #endif - rb_thread_signal_raise(th, signo2signm(sig)); + rb_thread_signal_raise(th, sig); break; } } @@ -638,6 +716,9 @@ trap(struct trap_arg *arg) #ifdef SIGQUIT case SIGQUIT: #endif +#ifdef SIGTERM + case SIGTERM: +#endif #ifdef SIGALRM case SIGALRM: #endif @@ -898,6 +979,11 @@ Init_signal(void) rb_define_module_function(mSignal, "trap", sig_trap, -1); rb_define_module_function(mSignal, "list", sig_list, 0); + rb_define_method(rb_eSignal, "initialize", esignal_init, -1); + rb_attr(rb_eSignal, rb_intern("signo"), 1, 0, 0); + rb_alias(rb_eSignal, rb_intern("signm"), rb_intern("message")); + rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1); + install_sighandler(SIGINT, sighandler); #ifdef SIGHUP install_sighandler(SIGHUP, sighandler); diff --git a/thread.c b/thread.c index 05f4840072..4c1fea3174 100644 --- a/thread.c +++ b/thread.c @@ -751,31 +751,25 @@ rb_thread_raise(int argc, VALUE *argv, rb_thread_t *th) } void -rb_thread_signal_raise(void *thptr, const char *sig) +rb_thread_signal_raise(void *thptr, int sig) { - VALUE argv[1]; - char buf[BUFSIZ]; + VALUE argv[2]; rb_thread_t *th = thptr; - - if (sig == 0) { - return; /* should not happen */ - } - snprintf(buf, BUFSIZ, "SIG%s", sig); - argv[0] = rb_exc_new3(rb_eSignal, rb_str_new2(buf)); - rb_thread_raise(1, argv, th->vm->main_thread); + + argv[0] = rb_eSignal; + argv[1] = INT2FIX(sig); + rb_thread_raise(2, argv, th->vm->main_thread); } void rb_thread_signal_exit(void *thptr) { - VALUE argv[1]; - VALUE args[2]; + VALUE argv[2]; rb_thread_t *th = thptr; - - args[0] = INT2NUM(EXIT_SUCCESS); - args[1] = rb_str_new2("exit"); - argv[0] = rb_class_new_instance(2, args, rb_eSystemExit); - rb_thread_raise(1, argv, th->vm->main_thread); + + argv[0] = rb_eSystemExit; + argv[1] = rb_str_new2("exit"); + rb_thread_raise(2, argv, th->vm->main_thread); } int diff --git a/version.h b/version.h index a9e65bde19..371c561622 100644 --- a/version.h +++ b/version.h @@ -1,7 +1,7 @@ #define RUBY_VERSION "1.9.0" -#define RUBY_RELEASE_DATE "2007-04-19" +#define RUBY_RELEASE_DATE "2007-04-20" #define RUBY_VERSION_CODE 190 -#define RUBY_RELEASE_CODE 20070419 +#define RUBY_RELEASE_CODE 20070420 #define RUBY_PATCHLEVEL 0 #define RUBY_VERSION_MAJOR 1 @@ -9,7 +9,7 @@ #define RUBY_VERSION_TEENY 0 #define RUBY_RELEASE_YEAR 2007 #define RUBY_RELEASE_MONTH 4 -#define RUBY_RELEASE_DAY 19 +#define RUBY_RELEASE_DAY 20 RUBY_EXTERN const char ruby_version[]; RUBY_EXTERN const char ruby_release_date[]; diff --git a/yarvcore.h b/yarvcore.h index 4961adfc75..56d17f0654 100644 --- a/yarvcore.h +++ b/yarvcore.h @@ -345,7 +345,6 @@ typedef struct rb_vm_struct { int thread_abort_on_exception; unsigned long trace_flag; - int exit_code; /* object management */ VALUE mark_object_ary;