platform/shared/ruby/signal.c in rhodes-3.1.1 vs platform/shared/ruby/signal.c in rhodes-3.2.0.beta.1

- old
+ new

@@ -32,11 +32,11 @@ # define ATOMIC_SET(var, val) ((var) = (val)) # define ATOMIC_INC(var) (++(var)) # define ATOMIC_DEC(var) (--(var)) #endif -#ifdef __BEOS__ +#if defined(__BEOS__) || defined(__HAIKU__) #undef SIGBUS #endif #if defined HAVE_SIGPROCMASK || defined HAVE_SIGSETMASK #define USE_TRAP_MASK 1 @@ -215,14 +215,15 @@ return signo2signm(no); } /* * call-seq: - * SignalException.new(sig) => signal_exception + * SignalException.new(sig_name) -> signal_exception + * SignalException.new(sig_number [, name]) -> signal_exception * - * Construct a new SignalException object. +sig+ should be a known - * signal name, or a signal number. + * Construct a new SignalException object. +sig_name+ should be a known + * signal name. */ static VALUE esignal_init(int argc, VALUE *argv, VALUE self) { @@ -273,21 +274,22 @@ return self; } /* * call-seq: - * signal_exception.signo => num + * signal_exception.signo -> num * * Returns a signal number. */ static VALUE esignal_signo(VALUE self) { return rb_iv_get(self, "signo"); } +/* :nodoc: */ static VALUE interrupt_init(int argc, VALUE *argv, VALUE self) { VALUE args[2]; @@ -303,30 +305,40 @@ raise(sig); } /* * call-seq: - * Process.kill(signal, pid, ...) => fixnum - * + * Process.kill(signal, pid, ...) -> fixnum + * * Sends the given signal to the specified process id(s), or to the * current process if _pid_ is zero. _signal_ may be an * integer signal number or a POSIX signal name (either with or without * a +SIG+ prefix). If _signal_ is negative (or starts * with a minus sign), kills process groups instead of * processes. Not all signals are available on all platforms. - * + * * pid = fork do * Signal.trap("HUP") { puts "Ouch!"; exit } * # ... do some work ... * end * # ... * Process.kill("HUP", pid) * Process.wait - * + * * <em>produces:</em> - * + * * Ouch! + * + * If _signal_ is an integer but wrong for signal, + * <code>Errno::EINVAL</code> or +RangeError+ will be raised. + * Otherwise unless _signal_ is a +String+ or a +Symbol+, and a known + * signal name, +ArgumentError+ will be raised. + * + * Also, <code>Errno::ESRCH</code> or +RangeError+ for invalid _pid_, + * <code>Errno::EPERM</code> when failed because of no privilege, + * will be raised. In these cases, signals may have been sent to + * preceding processes. */ VALUE rb_f_kill(int argc, VALUE *argv) { @@ -338,11 +350,11 @@ int i; const char *s; rb_secure(2); if (argc < 2) - rb_raise(rb_eArgError, "wrong number of arguments -- kill(sig, pid...)"); + rb_raise(rb_eArgError, "wrong number of arguments (%d for at least 2)", argc); switch (TYPE(argv[0])) { case T_FIXNUM: sig = FIX2INT(argv[0]); break; @@ -407,42 +419,38 @@ #ifdef __dietlibc__ #define sighandler_t sh_t #endif typedef RETSIGTYPE (*sighandler_t)(int); -#if defined SA_SIGINFO && !defined __SYMBIAN32__ +#ifdef USE_SIGALTSTACK typedef void ruby_sigaction_t(int, siginfo_t*, void*); #define SIGINFO_ARG , siginfo_t *info, void *ctx #else typedef RETSIGTYPE ruby_sigaction_t(int); #define SIGINFO_ARG #endif #ifdef POSIX_SIGNAL -#if defined(SIGSEGV) && defined(HAVE_SIGALTSTACK) -#define USE_SIGALTSTACK -#endif #ifdef USE_SIGALTSTACK #ifdef SIGSTKSZ #define ALT_STACK_SIZE (SIGSTKSZ*2) #else #define ALT_STACK_SIZE (4*1024) #endif /* alternate stack for SIGSEGV */ -static void -register_sigaltstack(void) +void +rb_register_sigaltstack(rb_thread_t *th) { - static void *altstack = 0; stack_t newSS, oldSS; - if (altstack) return; + if (th->altstack) return; - newSS.ss_sp = altstack = malloc(ALT_STACK_SIZE); + newSS.ss_sp = th->altstack = malloc(ALT_STACK_SIZE); if (newSS.ss_sp == NULL) /* should handle error */ - rb_bug("register_sigaltstack. malloc error\n"); + rb_bug("rb_register_sigaltstack. malloc error\n"); newSS.ss_size = ALT_STACK_SIZE; newSS.ss_flags = 0; sigaltstack(&newSS, &oldSS); /* ignore error. */ } @@ -456,11 +464,11 @@ #if 0 rb_trap_accept_nativethreads[signum] = 0; #endif sigemptyset(&sigact.sa_mask); -#if defined SA_SIGINFO && !defined __SYMBIAN32__ +#ifdef SA_SIGINFO sigact.sa_sigaction = (ruby_sigaction_t*)handler; sigact.sa_flags = SA_SIGINFO; #else sigact.sa_handler = handler; sigact.sa_flags = 0; @@ -474,11 +482,11 @@ if (signum == SIGSEGV) sigact.sa_flags |= SA_ONSTACK; #endif if (sigaction(signum, &sigact, &old) < 0) { if (errno != 0 && errno != EINVAL) { - rb_bug("sigaction error.\n"); + rb_bug_errno("sigaction", errno); } } return old.sa_handler; } @@ -512,11 +520,11 @@ ruby_signal(sig, sighandler); #endif } int -rb_signal_buff_size() +rb_signal_buff_size(void) { return signal_buff.size; } #if USE_TRAP_MASK @@ -532,11 +540,11 @@ #endif void rb_disable_interrupt(void) { -#if !defined(_WIN32) && !defined(__SYMBIAN32__) +#if USE_TRAP_MASK sigset_t mask; sigfillset(&mask); sigdelset(&mask, SIGVTALRM); sigdelset(&mask, SIGSEGV); pthread_sigmask(SIG_SETMASK, &mask, NULL); @@ -544,11 +552,11 @@ } void rb_enable_interrupt(void) { -#if !defined(_WIN32) && !defined(__SYMBIAN32__) +#if USE_TRAP_MASK sigset_t mask; sigemptyset(&mask); pthread_sigmask(SIG_SETMASK, &mask, NULL); #endif } @@ -593,11 +601,11 @@ if (ruby_stack_overflowed_p(th, info->si_addr)) { ruby_thread_stack_overflow(th); } #endif if (segv_received) { - fprintf(stderr, "SEGV recieved in SEGV handler\n"); + fprintf(stderr, "SEGV received in SEGV handler\n"); exit(EXIT_FAILURE); } else { extern int ruby_disable_gc_stress; segv_received = 1; @@ -662,16 +670,16 @@ case SIGUSR1: #endif #ifdef SIGUSR2 case SIGUSR2: #endif - rb_thread_signal_raise(th, sig); + rb_threadptr_signal_raise(th, sig); break; } } else if (cmd == Qundef) { - rb_thread_signal_exit(th); + rb_threadptr_signal_exit(th); } else { signal_exec(cmd, safe, sig); } } @@ -722,11 +730,11 @@ #endif #ifdef SIGSEGV case SIGSEGV: func = (sighandler_t)sigsegv; # ifdef USE_SIGALTSTACK - register_sigaltstack(); + rb_register_sigaltstack(GET_THREAD()); # endif break; #endif #ifdef SIGPIPE case SIGPIPE: @@ -874,36 +882,28 @@ #if USE_TRAP_MASK static VALUE trap_ensure(struct trap_arg *arg) { /* enable interrupt */ -#ifdef HAVE_SIGPROCMASK - sigprocmask(SIG_SETMASK, &arg->mask, NULL); -#else - sigsetmask(arg->mask); -#endif + pthread_sigmask(SIG_SETMASK, &arg->mask, NULL); trap_last_mask = arg->mask; return 0; } #endif void rb_trap_restore_mask(void) { #if USE_TRAP_MASK -# ifdef HAVE_SIGPROCMASK - sigprocmask(SIG_SETMASK, &trap_last_mask, NULL); -# else - sigsetmask(trap_last_mask); -# endif + pthread_sigmask(SIG_SETMASK, &trap_last_mask, NULL); #endif } /* * call-seq: - * Signal.trap( signal, command ) => obj - * Signal.trap( signal ) {| | block } => obj + * Signal.trap( signal, command ) -> obj + * Signal.trap( signal ) {| | block } -> obj * * Specifies the handling of signals. The first parameter is a signal * name (a string such as ``SIGALRM'', ``SIGUSR1'', and so on) or a * signal number. The characters ``SIG'' may be omitted from the * signal name. The command or block specifies code to be run when the @@ -933,45 +933,45 @@ sig_trap(int argc, VALUE *argv) { struct trap_arg arg; rb_secure(2); - if (argc == 0 || argc > 2) { - rb_raise(rb_eArgError, "wrong number of arguments -- trap(sig, cmd)/trap(sig){...}"); + if (argc < 1 || argc > 2) { + rb_raise(rb_eArgError, "wrong number of arguments (%d for 1..2)", argc); } arg.sig = trap_signm(argv[0]); if (argc == 1) { arg.cmd = rb_block_proc(); arg.func = sighandler; } - else if (argc == 2) { + else { arg.cmd = argv[1]; arg.func = trap_handler(&arg.cmd, arg.sig); } if (OBJ_TAINTED(arg.cmd)) { rb_raise(rb_eSecurityError, "Insecure: tainted signal trap"); } #if USE_TRAP_MASK - /* disable interrupt */ -# ifdef HAVE_SIGPROCMASK - sigfillset(&arg.mask); - sigprocmask(SIG_BLOCK, &arg.mask, &arg.mask); -# else - arg.mask = sigblock(~0); -# endif + { + sigset_t fullmask; - return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg); + /* disable interrupt */ + sigfillset(&fullmask); + pthread_sigmask(SIG_BLOCK, &fullmask, &arg.mask); + + return rb_ensure(trap, (VALUE)&arg, trap_ensure, (VALUE)&arg); + } #else return trap(&arg); #endif } /* * call-seq: - * Signal.list => a_hash + * Signal.list -> a_hash * * Returns a list of signal names mapped to the corresponding * underlying signal numbers. * * Signal.list #=> {"EXIT"=>0, "HUP"=>1, "INT"=>2, "QUIT"=>3, "ILL"=>4, "TRAP"=>5, "IOT"=>6, "ABRT"=>6, "FPE"=>8, "KILL"=>9, "BUS"=>7, "SEGV"=>11, "SYS"=>31, "PIPE"=>13, "ALRM"=>14, "TERM"=>15, "URG"=>23, "STOP"=>19, "TSTP"=>20, "CONT"=>18, "CHLD"=>17, "CLD"=>17, "TTIN"=>21, "TTOU"=>22, "IO"=>29, "XCPU"=>24, "XFSZ"=>25, "VTALRM"=>26, "PROF"=>27, "WINCH"=>28, "USR1"=>10, "USR2"=>12, "PWR"=>30, "POLL"=>29} @@ -1005,47 +1005,40 @@ { sighandler_t oldfunc; #if USE_TRAP_MASK # ifdef HAVE_SIGPROCMASK sigset_t mask; + sigset_t fullmask; # else int mask; + int fullmask; # endif #endif #if USE_TRAP_MASK /* disable interrupt */ -# ifdef HAVE_SIGPROCMASK - sigfillset(&mask); - sigprocmask(SIG_BLOCK, &mask, &mask); -# else - mask = sigblock(~0); -# endif + sigfillset(&fullmask); + pthread_sigmask(SIG_BLOCK, &fullmask, &mask); #endif oldfunc = ruby_signal(sig, SIG_DFL); if (oldfunc != SIG_DFL && oldfunc != SIG_IGN) { ruby_signal(sig, oldfunc); } else { GET_VM()->trap_list[sig].cmd = 0; } #if USE_TRAP_MASK -#ifdef HAVE_SIGPROCMASK sigdelset(&mask, sig); - sigprocmask(SIG_SETMASK, &mask, NULL); -#else - mask &= ~sigmask(sig); - sigsetmask(mask); -#endif + pthread_sigmask(SIG_SETMASK, &mask, NULL); trap_last_mask = mask; #endif } #endif void -ruby_sig_finalize() +ruby_sig_finalize(void) { sighandler_t oldfunc; oldfunc = ruby_signal(SIGINT, SIG_IGN); if (oldfunc == sighandler) { @@ -1136,10 +1129,10 @@ #ifdef SIGBUS install_sighandler(SIGBUS, sigbus); #endif #ifdef SIGSEGV # ifdef USE_SIGALTSTACK - register_sigaltstack(); + rb_register_sigaltstack(GET_THREAD()); # endif install_sighandler(SIGSEGV, (sighandler_t)sigsegv); #endif } #ifdef SIGPIPE