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