2000-05-09 04:53:16 +00:00
|
|
|
/**********************************************************************
|
1998-01-16 12:13:05 +00:00
|
|
|
|
|
|
|
signal.c -
|
|
|
|
|
|
|
|
$Author$
|
|
|
|
created at: Tue Dec 20 10:13:44 JST 1994
|
|
|
|
|
* encoding.c: provide basic features for M17N.
* parse.y: encoding aware parsing.
* parse.y (pragma_encoding): encoding specification pragma.
* parse.y (rb_intern3): encoding specified symbols.
* string.c (rb_str_length): length based on characters.
for older behavior, bytesize method added.
* string.c (rb_str_index_m): index based on characters. rindex as
well.
* string.c (succ_char): encoding aware succeeding string.
* string.c (rb_str_reverse): reverse based on characters.
* string.c (rb_str_inspect): encoding aware string description.
* string.c (rb_str_upcase_bang): encoding aware case conversion.
downcase, capitalize, swapcase as well.
* string.c (rb_str_tr_bang): tr based on characters. delete,
squeeze, tr_s, count as well.
* string.c (rb_str_split_m): split based on characters.
* string.c (rb_str_each_line): encoding aware each_line.
* string.c (rb_str_each_char): added. iteration based on
characters.
* string.c (rb_str_strip_bang): encoding aware whitespace
stripping. lstrip, rstrip as well.
* string.c (rb_str_justify): encoding aware justifying (ljust,
rjust, center).
* string.c (str_encoding): get encoding attribute from a string.
* re.c (rb_reg_initialize): encoding aware regular expression
* sprintf.c (rb_str_format): formatting (i.e. length count) based
on characters.
* io.c (rb_io_getc): getc to return one-character string.
for older behavior, getbyte method added.
* ext/stringio/stringio.c (strio_getc): ditto.
* io.c (rb_io_ungetc): allow pushing arbitrary string at the
current reading point.
* ext/stringio/stringio.c (strio_ungetc): ditto.
* ext/strscan/strscan.c: encoding support.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@13261 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-08-25 03:29:39 +00:00
|
|
|
Copyright (C) 1993-2007 Yukihiro Matsumoto
|
2000-05-01 09:42:38 +00:00
|
|
|
Copyright (C) 2000 Network Applied Communication Laboratory, Inc.
|
2000-05-09 04:53:16 +00:00
|
|
|
Copyright (C) 2000 Information-technology Promotion Agency, Japan
|
2000-05-01 09:42:38 +00:00
|
|
|
|
2000-05-09 04:53:16 +00:00
|
|
|
**********************************************************************/
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2020-05-08 18:31:09 +09:00
|
|
|
#include "ruby/internal/config.h"
|
2019-12-04 17:16:30 +09:00
|
|
|
|
|
|
|
#include <errno.h>
|
1998-01-16 12:13:05 +00:00
|
|
|
#include <signal.h>
|
|
|
|
#include <stdio.h>
|
2019-12-04 17:16:30 +09:00
|
|
|
|
2013-05-14 15:44:14 +00:00
|
|
|
#ifdef HAVE_UNISTD_H
|
|
|
|
# include <unistd.h>
|
|
|
|
#endif
|
2019-12-04 17:16:30 +09:00
|
|
|
|
2014-10-17 05:14:14 +00:00
|
|
|
#ifdef HAVE_SYS_UIO_H
|
2019-12-04 17:16:30 +09:00
|
|
|
# include <sys/uio.h>
|
2014-10-17 05:14:14 +00:00
|
|
|
#endif
|
2019-12-04 17:16:30 +09:00
|
|
|
|
2014-12-13 21:31:31 +00:00
|
|
|
#ifdef HAVE_UCONTEXT_H
|
2019-12-04 17:16:30 +09:00
|
|
|
# include <ucontext.h>
|
2014-12-13 21:31:31 +00:00
|
|
|
#endif
|
2011-06-11 14:27:08 +00:00
|
|
|
|
2021-04-29 15:12:44 +02:00
|
|
|
#ifdef HAVE_PTHREAD_H
|
2019-12-04 17:16:30 +09:00
|
|
|
# include <pthread.h>
|
2013-07-12 07:37:31 +00:00
|
|
|
#endif
|
|
|
|
|
2019-12-04 17:16:30 +09:00
|
|
|
#include "debug_counter.h"
|
|
|
|
#include "eval_intern.h"
|
|
|
|
#include "internal.h"
|
2023-05-15 12:08:00 +08:00
|
|
|
#include "internal/error.h"
|
2019-12-04 17:16:30 +09:00
|
|
|
#include "internal/eval.h"
|
|
|
|
#include "internal/sanitizers.h"
|
|
|
|
#include "internal/signal.h"
|
|
|
|
#include "internal/string.h"
|
|
|
|
#include "internal/thread.h"
|
|
|
|
#include "ruby_atomic.h"
|
|
|
|
#include "vm_core.h"
|
2020-12-12 06:54:46 +09:00
|
|
|
#include "ractor_core.h"
|
2025-04-30 18:35:25 +09:00
|
|
|
#include "ruby/internal/attr/nonstring.h"
|
2019-12-04 17:16:30 +09:00
|
|
|
|
2012-11-27 10:21:59 +00:00
|
|
|
#ifdef NEED_RUBY_ATOMIC_OPS
|
2011-06-23 04:33:13 +00:00
|
|
|
rb_atomic_t
|
|
|
|
ruby_atomic_exchange(rb_atomic_t *ptr, rb_atomic_t val)
|
2011-06-11 14:27:08 +00:00
|
|
|
{
|
|
|
|
rb_atomic_t old = *ptr;
|
|
|
|
*ptr = val;
|
|
|
|
return old;
|
2012-11-27 10:21:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rb_atomic_t
|
|
|
|
ruby_atomic_compare_and_swap(rb_atomic_t *ptr, rb_atomic_t cmp,
|
|
|
|
rb_atomic_t newval)
|
|
|
|
{
|
|
|
|
rb_atomic_t old = *ptr;
|
|
|
|
if (old == cmp) {
|
2013-10-26 10:07:11 +00:00
|
|
|
*ptr = newval;
|
2012-11-27 10:21:59 +00:00
|
|
|
}
|
|
|
|
return old;
|
2011-06-11 14:27:08 +00:00
|
|
|
}
|
* include/ruby/signal.h: removed.
* common.mk, class.c, eval.c, eval_intern.h, file.c, gc.c, hash.c,
io.c, process.c, signal.c: vm_core.h: ditto.
Some unused external global variables are also removed.
(rb_prohibit_interrupt, rb_trap_immediate, rb_trap_pending,
rb_thread_critical)
* ext/openssl/ossl_ssl.c, ext/openssl/ossl_x509store.c,
ext/readline/readline.c, ext/socket/depend,
ext/socket/socket.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@19080 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2008-09-03 08:00:05 +00:00
|
|
|
#endif
|
|
|
|
|
2018-07-04 16:10:14 +00:00
|
|
|
#define FOREACH_SIGNAL(sig, offset) \
|
|
|
|
for (sig = siglist + (offset); sig < siglist + numberof(siglist); ++sig)
|
|
|
|
enum { LONGEST_SIGNAME = 7 }; /* MIGRATE and RETRACT */
|
2008-04-26 08:30:22 +00:00
|
|
|
static const struct signals {
|
2018-07-04 16:10:14 +00:00
|
|
|
char signm[LONGEST_SIGNAME + 1];
|
1998-01-16 12:13:05 +00:00
|
|
|
int signo;
|
|
|
|
} siglist [] = {
|
2005-06-12 16:56:06 +00:00
|
|
|
{"EXIT", 0},
|
1998-01-16 12:13:05 +00:00
|
|
|
#ifdef SIGHUP
|
2002-04-24 04:54:16 +00:00
|
|
|
{"HUP", SIGHUP},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
2002-04-24 04:54:16 +00:00
|
|
|
{"INT", SIGINT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#ifdef SIGQUIT
|
2002-04-24 04:54:16 +00:00
|
|
|
{"QUIT", SIGQUIT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGILL
|
2002-04-24 04:54:16 +00:00
|
|
|
{"ILL", SIGILL},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGTRAP
|
2002-04-24 04:54:16 +00:00
|
|
|
{"TRAP", SIGTRAP},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGABRT
|
2002-04-24 04:54:16 +00:00
|
|
|
{"ABRT", SIGABRT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
2013-03-25 05:39:29 +00:00
|
|
|
#ifdef SIGIOT
|
|
|
|
{"IOT", SIGIOT},
|
|
|
|
#endif
|
1998-01-16 12:13:05 +00:00
|
|
|
#ifdef SIGEMT
|
2002-04-24 04:54:16 +00:00
|
|
|
{"EMT", SIGEMT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGFPE
|
2002-04-24 04:54:16 +00:00
|
|
|
{"FPE", SIGFPE},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGKILL
|
2002-04-24 04:54:16 +00:00
|
|
|
{"KILL", SIGKILL},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGBUS
|
2002-04-24 04:54:16 +00:00
|
|
|
{"BUS", SIGBUS},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGSEGV
|
2002-04-24 04:54:16 +00:00
|
|
|
{"SEGV", SIGSEGV},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGSYS
|
2002-04-24 04:54:16 +00:00
|
|
|
{"SYS", SIGSYS},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGPIPE
|
2002-04-24 04:54:16 +00:00
|
|
|
{"PIPE", SIGPIPE},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGALRM
|
2002-04-24 04:54:16 +00:00
|
|
|
{"ALRM", SIGALRM},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGTERM
|
2002-04-24 04:54:16 +00:00
|
|
|
{"TERM", SIGTERM},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGURG
|
2002-04-24 04:54:16 +00:00
|
|
|
{"URG", SIGURG},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGSTOP
|
2002-04-24 04:54:16 +00:00
|
|
|
{"STOP", SIGSTOP},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGTSTP
|
2002-04-24 04:54:16 +00:00
|
|
|
{"TSTP", SIGTSTP},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGCONT
|
2002-04-24 04:54:16 +00:00
|
|
|
{"CONT", SIGCONT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
2023-05-15 23:14:51 +09:00
|
|
|
#ifdef RUBY_SIGCHLD
|
2018-07-05 03:02:33 +00:00
|
|
|
{"CHLD", RUBY_SIGCHLD },
|
|
|
|
{"CLD", RUBY_SIGCHLD },
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGTTIN
|
2002-04-24 04:54:16 +00:00
|
|
|
{"TTIN", SIGTTIN},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGTTOU
|
2002-04-24 04:54:16 +00:00
|
|
|
{"TTOU", SIGTTOU},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGIO
|
2002-04-24 04:54:16 +00:00
|
|
|
{"IO", SIGIO},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGXCPU
|
2002-04-24 04:54:16 +00:00
|
|
|
{"XCPU", SIGXCPU},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGXFSZ
|
2002-04-24 04:54:16 +00:00
|
|
|
{"XFSZ", SIGXFSZ},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGVTALRM
|
2002-04-24 04:54:16 +00:00
|
|
|
{"VTALRM", SIGVTALRM},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGPROF
|
2002-04-24 04:54:16 +00:00
|
|
|
{"PROF", SIGPROF},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGWINCH
|
2002-04-24 04:54:16 +00:00
|
|
|
{"WINCH", SIGWINCH},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR1
|
2002-04-24 04:54:16 +00:00
|
|
|
{"USR1", SIGUSR1},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR2
|
2002-04-24 04:54:16 +00:00
|
|
|
{"USR2", SIGUSR2},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGLOST
|
2002-04-24 04:54:16 +00:00
|
|
|
{"LOST", SIGLOST},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGMSG
|
2002-04-24 04:54:16 +00:00
|
|
|
{"MSG", SIGMSG},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGPWR
|
2002-04-24 04:54:16 +00:00
|
|
|
{"PWR", SIGPWR},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGPOLL
|
2002-04-24 04:54:16 +00:00
|
|
|
{"POLL", SIGPOLL},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGDANGER
|
2002-04-24 04:54:16 +00:00
|
|
|
{"DANGER", SIGDANGER},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGMIGRATE
|
2002-04-24 04:54:16 +00:00
|
|
|
{"MIGRATE", SIGMIGRATE},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGPRE
|
2002-04-24 04:54:16 +00:00
|
|
|
{"PRE", SIGPRE},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGGRANT
|
2002-04-24 04:54:16 +00:00
|
|
|
{"GRANT", SIGGRANT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGRETRACT
|
2002-04-24 04:54:16 +00:00
|
|
|
{"RETRACT", SIGRETRACT},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGSOUND
|
2002-04-24 04:54:16 +00:00
|
|
|
{"SOUND", SIGSOUND},
|
2001-05-16 09:05:54 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGINFO
|
2002-04-24 04:54:16 +00:00
|
|
|
{"INFO", SIGINFO},
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
2019-08-01 14:25:15 +09:00
|
|
|
static const char signame_prefix[] = "SIG";
|
|
|
|
static const int signame_prefix_len = 3;
|
2014-03-31 02:34:43 +00:00
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
static int
|
2018-03-10 11:26:54 +00:00
|
|
|
signm2signo(VALUE *sig_ptr, int negative, int exit, int *prefix_ptr)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2008-04-26 08:30:22 +00:00
|
|
|
const struct signals *sigs;
|
2018-03-10 11:26:54 +00:00
|
|
|
VALUE vsig = *sig_ptr;
|
|
|
|
const char *nm;
|
2018-07-04 16:10:14 +00:00
|
|
|
long len, nmlen;
|
2018-03-10 11:26:54 +00:00
|
|
|
int prefix = 0;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2018-03-10 11:26:54 +00:00
|
|
|
if (RB_SYMBOL_P(vsig)) {
|
|
|
|
*sig_ptr = vsig = rb_sym2str(vsig);
|
|
|
|
}
|
|
|
|
else if (!RB_TYPE_P(vsig, T_STRING)) {
|
|
|
|
VALUE str = rb_check_string_type(vsig);
|
|
|
|
if (NIL_P(str)) {
|
|
|
|
rb_raise(rb_eArgError, "bad signal type %s",
|
|
|
|
rb_obj_classname(vsig));
|
|
|
|
}
|
|
|
|
*sig_ptr = vsig = str;
|
|
|
|
}
|
|
|
|
|
|
|
|
rb_must_asciicompat(vsig);
|
|
|
|
RSTRING_GETMEM(vsig, nm, len);
|
|
|
|
if (memchr(nm, '\0', len)) {
|
|
|
|
rb_raise(rb_eArgError, "signal name with null byte");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (len > 0 && nm[0] == '-') {
|
|
|
|
if (!negative)
|
|
|
|
rb_raise(rb_eArgError, "negative signal name: % "PRIsVALUE, vsig);
|
|
|
|
prefix = 1;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
negative = 0;
|
|
|
|
}
|
|
|
|
if (len >= prefix + signame_prefix_len) {
|
2019-08-01 14:27:19 +09:00
|
|
|
if (memcmp(nm + prefix, signame_prefix, signame_prefix_len) == 0)
|
2018-03-10 11:26:54 +00:00
|
|
|
prefix += signame_prefix_len;
|
|
|
|
}
|
|
|
|
if (len <= (long)prefix) {
|
2020-06-16 15:46:30 +09:00
|
|
|
goto unsupported;
|
2018-03-10 11:26:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (prefix_ptr) *prefix_ptr = prefix;
|
2018-07-04 16:10:14 +00:00
|
|
|
nmlen = len - prefix;
|
|
|
|
nm += prefix;
|
|
|
|
if (nmlen > LONGEST_SIGNAME) goto unsupported;
|
|
|
|
FOREACH_SIGNAL(sigs, !exit) {
|
|
|
|
if (memcmp(sigs->signm, nm, nmlen) == 0 &&
|
|
|
|
sigs->signm[nmlen] == '\0') {
|
2018-03-10 11:26:54 +00:00
|
|
|
return negative ? -sigs->signo : sigs->signo;
|
|
|
|
}
|
|
|
|
}
|
2020-06-16 15:46:30 +09:00
|
|
|
|
|
|
|
unsupported:
|
|
|
|
if (prefix == signame_prefix_len) {
|
|
|
|
prefix = 0;
|
|
|
|
}
|
|
|
|
else if (prefix > signame_prefix_len) {
|
|
|
|
prefix -= signame_prefix_len;
|
|
|
|
len -= prefix;
|
|
|
|
vsig = rb_str_subseq(vsig, prefix, len);
|
|
|
|
prefix = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
len -= prefix;
|
|
|
|
vsig = rb_str_subseq(vsig, prefix, len);
|
|
|
|
prefix = signame_prefix_len;
|
|
|
|
}
|
2024-01-19 16:03:38 +09:00
|
|
|
rb_raise(rb_eArgError, "unsupported signal '%.*s%"PRIsVALUE"'",
|
2020-06-16 15:46:30 +09:00
|
|
|
prefix, signame_prefix, vsig);
|
2020-06-24 16:23:59 +09:00
|
|
|
UNREACHABLE_RETURN(0);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2005-11-08 08:49:45 +00:00
|
|
|
static const char*
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 10:44:21 +00:00
|
|
|
signo2signm(int no)
|
1999-08-13 05:45:20 +00:00
|
|
|
{
|
2008-04-26 08:30:22 +00:00
|
|
|
const struct signals *sigs;
|
1999-08-13 05:45:20 +00:00
|
|
|
|
2018-07-04 16:10:14 +00:00
|
|
|
FOREACH_SIGNAL(sigs, 0) {
|
1999-08-13 05:45:20 +00:00
|
|
|
if (sigs->signo == no)
|
|
|
|
return sigs->signm;
|
2018-07-04 16:10:14 +00:00
|
|
|
}
|
1999-08-13 05:45:20 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2012-11-19 09:43:53 +00:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2016-09-28 04:00:27 +00:00
|
|
|
* Signal.signame(signo) -> string or nil
|
2012-11-19 09:43:53 +00:00
|
|
|
*
|
2016-09-28 04:00:27 +00:00
|
|
|
* Convert signal number to signal name.
|
|
|
|
* Returns +nil+ if the signo is an invalid signal number.
|
2012-11-19 09:43:53 +00:00
|
|
|
*
|
|
|
|
* Signal.trap("INT") { |signo| puts Signal.signame(signo) }
|
|
|
|
* Process.kill("INT", 0)
|
|
|
|
*
|
|
|
|
* <em>produces:</em>
|
|
|
|
*
|
|
|
|
* INT
|
|
|
|
*/
|
|
|
|
static VALUE
|
|
|
|
sig_signame(VALUE recv, VALUE signo)
|
|
|
|
{
|
|
|
|
const char *signame = signo2signm(NUM2INT(signo));
|
2015-03-02 04:04:30 +00:00
|
|
|
if (!signame) return Qnil;
|
2012-11-19 09:43:53 +00:00
|
|
|
return rb_str_new_cstr(signame);
|
|
|
|
}
|
|
|
|
|
2003-10-01 15:14:23 +00:00
|
|
|
const char *
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 10:44:21 +00:00
|
|
|
ruby_signal_name(int no)
|
2003-09-29 02:44:49 +00:00
|
|
|
{
|
|
|
|
return signo2signm(no);
|
|
|
|
}
|
|
|
|
|
2014-09-21 02:03:34 +00:00
|
|
|
static VALUE
|
|
|
|
rb_signo2signm(int signo)
|
|
|
|
{
|
|
|
|
const char *const signm = signo2signm(signo);
|
|
|
|
if (signm) {
|
|
|
|
return rb_sprintf("SIG%s", signm);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return rb_sprintf("SIG%u", signo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-19 17:37:03 +00:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 21:07:33 +00:00
|
|
|
* SignalException.new(sig_name) -> signal_exception
|
|
|
|
* SignalException.new(sig_number [, name]) -> signal_exception
|
2007-04-19 17:37:03 +00:00
|
|
|
*
|
2010-04-30 04:35:16 +00:00
|
|
|
* Construct a new SignalException object. +sig_name+ should be a known
|
|
|
|
* signal name.
|
2007-04-19 17:37:03 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
esignal_init(int argc, VALUE *argv, VALUE self)
|
|
|
|
{
|
|
|
|
int argnum = 1;
|
|
|
|
VALUE sig = Qnil;
|
|
|
|
int signo;
|
|
|
|
|
|
|
|
if (argc > 0) {
|
|
|
|
sig = rb_check_to_integer(argv[0], "to_int");
|
|
|
|
if (!NIL_P(sig)) argnum = 2;
|
2008-05-29 17:08:48 +00:00
|
|
|
else sig = argv[0];
|
2007-04-19 17:37:03 +00:00
|
|
|
}
|
2012-03-14 21:10:34 +00:00
|
|
|
rb_check_arity(argc, 1, argnum);
|
2007-04-19 17:37:03 +00:00
|
|
|
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 {
|
2014-09-21 02:03:34 +00:00
|
|
|
sig = rb_signo2signm(signo);
|
2007-04-19 17:37:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2018-03-10 11:26:54 +00:00
|
|
|
int prefix;
|
|
|
|
signo = signm2signo(&sig, FALSE, FALSE, &prefix);
|
|
|
|
if (prefix != signame_prefix_len) {
|
|
|
|
sig = rb_str_append(rb_str_new_cstr("SIG"), sig);
|
2007-04-19 17:37:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
rb_call_super(1, &sig);
|
2015-02-23 07:05:30 +00:00
|
|
|
rb_ivar_set(self, id_signo, INT2NUM(signo));
|
2007-04-19 17:37:03 +00:00
|
|
|
|
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2008-05-30 13:32:39 +00:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 21:07:33 +00:00
|
|
|
* signal_exception.signo -> num
|
2008-05-30 13:32:39 +00:00
|
|
|
*
|
|
|
|
* Returns a signal number.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static VALUE
|
|
|
|
esignal_signo(VALUE self)
|
|
|
|
{
|
2015-02-23 07:05:30 +00:00
|
|
|
return rb_ivar_get(self, id_signo);
|
2008-05-30 13:32:39 +00:00
|
|
|
}
|
|
|
|
|
2009-09-13 10:34:35 +00:00
|
|
|
/* :nodoc: */
|
2007-04-19 17:37:03 +00:00
|
|
|
static VALUE
|
|
|
|
interrupt_init(int argc, VALUE *argv, VALUE self)
|
|
|
|
{
|
|
|
|
VALUE args[2];
|
|
|
|
|
|
|
|
args[0] = INT2FIX(SIGINT);
|
2018-12-06 07:49:24 +00:00
|
|
|
args[1] = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil;
|
2007-05-29 17:13:05 +00:00
|
|
|
return rb_call_super(2, args);
|
2007-04-19 17:37:03 +00:00
|
|
|
}
|
|
|
|
|
2023-12-19 02:55:24 +00:00
|
|
|
#if defined(USE_SIGALTSTACK) || defined(_WIN32)
|
2023-12-18 16:37:52 -05:00
|
|
|
static void reset_sigmask(int sig);
|
|
|
|
#endif
|
2018-09-25 18:13:29 +00:00
|
|
|
|
2007-04-19 17:37:03 +00:00
|
|
|
void
|
|
|
|
ruby_default_signal(int sig)
|
|
|
|
{
|
2018-09-25 18:13:29 +00:00
|
|
|
#if USE_DEBUG_COUNTER
|
|
|
|
rb_debug_counter_show_results("killed by signal.");
|
|
|
|
#endif
|
|
|
|
|
2007-04-19 17:37:03 +00:00
|
|
|
signal(sig, SIG_DFL);
|
2023-12-19 02:55:24 +00:00
|
|
|
#if defined(USE_SIGALTSTACK) || defined(_WIN32)
|
2023-12-18 16:37:52 -05:00
|
|
|
reset_sigmask(sig);
|
|
|
|
#endif
|
2007-04-19 17:37:03 +00:00
|
|
|
raise(sig);
|
|
|
|
}
|
|
|
|
|
2020-12-12 16:06:19 +09:00
|
|
|
static void sighandler(int sig);
|
2014-05-10 16:10:32 +00:00
|
|
|
static int signal_ignored(int sig);
|
|
|
|
static void signal_enque(int sig);
|
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
VALUE
|
2014-06-18 06:16:39 +00:00
|
|
|
rb_f_kill(int argc, const VALUE *argv)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2013-05-12 08:41:46 +00:00
|
|
|
#ifndef HAVE_KILLPG
|
2010-12-29 01:07:26 +00:00
|
|
|
#define killpg(pg, sig) kill(-(pg), (sig))
|
2007-04-19 17:37:03 +00:00
|
|
|
#endif
|
1998-01-16 12:13:05 +00:00
|
|
|
int sig;
|
|
|
|
int i;
|
2014-07-30 14:27:15 +00:00
|
|
|
VALUE str;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2012-03-14 21:10:34 +00:00
|
|
|
rb_check_arity(argc, 2, UNLIMITED_ARGUMENTS);
|
|
|
|
|
2018-03-10 11:26:54 +00:00
|
|
|
if (FIXNUM_P(argv[0])) {
|
2000-09-19 07:54:28 +00:00
|
|
|
sig = FIX2INT(argv[0]);
|
2018-03-10 11:26:54 +00:00
|
|
|
}
|
|
|
|
else {
|
2014-07-30 14:27:15 +00:00
|
|
|
str = argv[0];
|
2018-03-10 11:26:54 +00:00
|
|
|
sig = signm2signo(&str, TRUE, FALSE, NULL);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-05-10 16:10:32 +00:00
|
|
|
if (argc <= 1) return INT2FIX(0);
|
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
if (sig < 0) {
|
|
|
|
sig = -sig;
|
|
|
|
for (i=1; i<argc; i++) {
|
2007-04-19 17:37:03 +00:00
|
|
|
if (killpg(NUM2PIDT(argv[i]), sig) < 0)
|
1998-01-16 12:13:05 +00:00
|
|
|
rb_sys_fail(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
2020-03-10 02:22:11 +09:00
|
|
|
const rb_pid_t self = (GET_THREAD() == GET_VM()->ractor.main_thread) ? getpid() : -1;
|
2014-05-10 16:10:32 +00:00
|
|
|
int wakeup = 0;
|
2022-07-21 09:23:58 -07:00
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
for (i=1; i<argc; i++) {
|
2014-05-10 16:10:32 +00:00
|
|
|
rb_pid_t pid = NUM2PIDT(argv[i]);
|
2022-07-21 09:23:58 -07:00
|
|
|
|
2014-05-10 16:10:32 +00:00
|
|
|
if ((sig != 0) && (self != -1) && (pid == self)) {
|
2014-10-06 07:23:06 +00:00
|
|
|
int t;
|
2014-05-10 16:10:32 +00:00
|
|
|
/*
|
|
|
|
* When target pid is self, many caller assume signal will be
|
|
|
|
* delivered immediately and synchronously.
|
|
|
|
*/
|
|
|
|
switch (sig) {
|
|
|
|
case SIGSEGV:
|
|
|
|
#ifdef SIGBUS
|
|
|
|
case SIGBUS:
|
2014-05-11 01:02:47 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGKILL
|
|
|
|
case SIGKILL:
|
|
|
|
#endif
|
2016-01-26 04:09:31 +00:00
|
|
|
#ifdef SIGILL
|
|
|
|
case SIGILL:
|
|
|
|
#endif
|
|
|
|
#ifdef SIGFPE
|
|
|
|
case SIGFPE:
|
|
|
|
#endif
|
2014-05-11 01:02:47 +00:00
|
|
|
#ifdef SIGSTOP
|
|
|
|
case SIGSTOP:
|
2014-05-10 16:10:32 +00:00
|
|
|
#endif
|
2017-06-12 04:52:25 +00:00
|
|
|
kill(pid, sig);
|
2014-05-10 16:10:32 +00:00
|
|
|
break;
|
|
|
|
default:
|
2014-10-06 07:23:06 +00:00
|
|
|
t = signal_ignored(sig);
|
|
|
|
if (t) {
|
2014-10-07 14:40:16 +00:00
|
|
|
if (t < 0 && kill(pid, sig))
|
|
|
|
rb_sys_fail(0);
|
2014-10-06 07:23:06 +00:00
|
|
|
break;
|
|
|
|
}
|
2014-05-10 16:10:32 +00:00
|
|
|
signal_enque(sig);
|
|
|
|
wakeup = 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (kill(pid, sig) < 0) {
|
|
|
|
rb_sys_fail(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (wakeup) {
|
2020-03-10 02:22:11 +09:00
|
|
|
rb_threadptr_check_signal(GET_VM()->ractor.main_thread);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
}
|
2013-03-19 04:40:22 +00:00
|
|
|
rb_thread_execute_interrupts(rb_thread_current());
|
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
return INT2FIX(i-1);
|
|
|
|
}
|
|
|
|
|
2008-10-24 18:58:52 +00:00
|
|
|
static struct {
|
2008-09-04 04:22:04 +00:00
|
|
|
rb_atomic_t cnt[RUBY_NSIG];
|
|
|
|
rb_atomic_t size;
|
|
|
|
} signal_buff;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2013-10-06 13:52:39 +00:00
|
|
|
#define sighandler_t ruby_sighandler_t
|
2002-08-16 07:23:04 +00:00
|
|
|
|
2010-01-25 03:11:46 +00:00
|
|
|
#ifdef USE_SIGALTSTACK
|
2008-11-27 07:12:35 +00:00
|
|
|
typedef void ruby_sigaction_t(int, siginfo_t*, void*);
|
|
|
|
#define SIGINFO_ARG , siginfo_t *info, void *ctx
|
2014-05-25 03:46:55 +00:00
|
|
|
#define SIGINFO_CTX ctx
|
2008-11-27 07:12:35 +00:00
|
|
|
#else
|
2020-12-12 16:06:19 +09:00
|
|
|
typedef void ruby_sigaction_t(int);
|
2008-11-27 07:12:35 +00:00
|
|
|
#define SIGINFO_ARG
|
2014-05-25 03:46:55 +00:00
|
|
|
#define SIGINFO_CTX 0
|
2008-11-27 07:12:35 +00:00
|
|
|
#endif
|
2002-01-21 07:44:06 +00:00
|
|
|
|
2008-11-21 18:27:33 +00:00
|
|
|
#ifdef USE_SIGALTSTACK
|
2020-07-22 21:26:21 +09:00
|
|
|
/* XXX: BSD_vfprintf() uses >1500B stack and x86-64 need >5KiB stack. */
|
|
|
|
#define RUBY_SIGALTSTACK_SIZE (16*1024)
|
|
|
|
|
2018-04-20 21:38:27 +00:00
|
|
|
static int
|
2013-09-12 05:37:04 +00:00
|
|
|
rb_sigaltstack_size(void)
|
2012-12-15 14:20:12 +00:00
|
|
|
{
|
2020-07-22 21:26:21 +09:00
|
|
|
int size = RUBY_SIGALTSTACK_SIZE;
|
2012-12-15 14:20:12 +00:00
|
|
|
|
|
|
|
#ifdef MINSIGSTKSZ
|
2019-10-05 07:37:19 +09:00
|
|
|
{
|
|
|
|
int minsigstksz = (int)MINSIGSTKSZ;
|
|
|
|
if (size < minsigstksz)
|
|
|
|
size = minsigstksz;
|
|
|
|
}
|
2012-12-15 14:20:12 +00:00
|
|
|
#endif
|
|
|
|
#if defined(HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
|
|
|
|
{
|
|
|
|
int pagesize;
|
2012-12-15 17:10:50 +00:00
|
|
|
pagesize = (int)sysconf(_SC_PAGE_SIZE);
|
2012-12-15 14:20:12 +00:00
|
|
|
if (size < pagesize)
|
|
|
|
size = pagesize;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2020-03-06 21:32:42 +09:00
|
|
|
static int rb_sigaltstack_size_value = 0;
|
|
|
|
|
|
|
|
void *
|
|
|
|
rb_allocate_sigaltstack(void)
|
|
|
|
{
|
2021-09-06 14:22:24 +09:00
|
|
|
void *altstack;
|
2020-03-06 21:32:42 +09:00
|
|
|
if (!rb_sigaltstack_size_value) {
|
|
|
|
rb_sigaltstack_size_value = rb_sigaltstack_size();
|
|
|
|
}
|
2021-09-06 14:22:24 +09:00
|
|
|
altstack = malloc(rb_sigaltstack_size_value);
|
|
|
|
if (!altstack) rb_memerror();
|
|
|
|
return altstack;
|
2020-03-06 21:32:42 +09:00
|
|
|
}
|
|
|
|
|
2008-11-21 18:27:33 +00:00
|
|
|
/* alternate stack for SIGSEGV */
|
2018-04-20 21:38:27 +00:00
|
|
|
void *
|
2020-03-06 21:32:42 +09:00
|
|
|
rb_register_sigaltstack(void *altstack)
|
2008-11-24 14:25:45 +00:00
|
|
|
{
|
2008-11-21 18:27:33 +00:00
|
|
|
stack_t newSS, oldSS;
|
|
|
|
|
2020-03-06 21:32:42 +09:00
|
|
|
newSS.ss_size = rb_sigaltstack_size_value;
|
|
|
|
newSS.ss_sp = altstack;
|
2008-11-21 18:27:33 +00:00
|
|
|
newSS.ss_flags = 0;
|
|
|
|
|
2009-02-06 11:40:33 +00:00
|
|
|
sigaltstack(&newSS, &oldSS); /* ignore error. */
|
2018-04-20 21:38:27 +00:00
|
|
|
|
|
|
|
return newSS.ss_sp;
|
2008-11-21 18:27:33 +00:00
|
|
|
}
|
2011-07-30 01:57:06 +00:00
|
|
|
#endif /* USE_SIGALTSTACK */
|
2008-11-21 18:27:33 +00:00
|
|
|
|
2012-05-17 02:48:59 +00:00
|
|
|
#ifdef POSIX_SIGNAL
|
2002-01-21 07:44:06 +00:00
|
|
|
static sighandler_t
|
2005-11-08 08:49:45 +00:00
|
|
|
ruby_signal(int signum, sighandler_t handler)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2002-01-21 07:44:06 +00:00
|
|
|
struct sigaction sigact, old;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2008-04-26 08:30:22 +00:00
|
|
|
#if 0
|
2005-02-21 09:33:34 +00:00
|
|
|
rb_trap_accept_nativethreads[signum] = 0;
|
2008-04-26 08:30:22 +00:00
|
|
|
#endif
|
2005-02-21 09:33:34 +00:00
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
sigemptyset(&sigact.sa_mask);
|
2024-01-30 20:34:05 +09:00
|
|
|
#if defined(USE_SIGALTSTACK) && !defined(__wasm__)
|
2014-09-05 15:50:24 +00:00
|
|
|
if (handler == SIG_IGN || handler == SIG_DFL) {
|
|
|
|
sigact.sa_handler = handler;
|
|
|
|
sigact.sa_flags = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sigact.sa_sigaction = (ruby_sigaction_t*)handler;
|
|
|
|
sigact.sa_flags = SA_SIGINFO;
|
|
|
|
}
|
2007-11-30 14:49:45 +00:00
|
|
|
#else
|
|
|
|
sigact.sa_handler = handler;
|
1998-01-16 12:13:05 +00:00
|
|
|
sigact.sa_flags = 0;
|
2007-11-30 14:49:45 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-09 14:31:27 +00:00
|
|
|
switch (signum) {
|
2008-11-21 18:27:33 +00:00
|
|
|
#if defined(SA_ONSTACK) && defined(USE_SIGALTSTACK)
|
2014-05-09 14:31:27 +00:00
|
|
|
case SIGSEGV:
|
2012-08-23 02:59:24 +00:00
|
|
|
#ifdef SIGBUS
|
2014-05-09 14:31:27 +00:00
|
|
|
case SIGBUS:
|
2012-08-23 02:59:24 +00:00
|
|
|
#endif
|
2008-11-27 07:32:56 +00:00
|
|
|
sigact.sa_flags |= SA_ONSTACK;
|
2014-05-09 14:31:27 +00:00
|
|
|
break;
|
2008-11-21 18:27:33 +00:00
|
|
|
#endif
|
2014-05-09 14:31:27 +00:00
|
|
|
}
|
2013-07-14 17:43:55 +00:00
|
|
|
(void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old));
|
2008-12-04 04:57:58 +00:00
|
|
|
if (sigaction(signum, &sigact, &old) < 0) {
|
2014-09-21 02:42:40 +00:00
|
|
|
return SIG_ERR;
|
2008-12-04 04:57:58 +00:00
|
|
|
}
|
2014-05-29 14:27:53 +00:00
|
|
|
if (old.sa_flags & SA_SIGINFO)
|
2017-06-08 07:41:38 +00:00
|
|
|
handler = (sighandler_t)old.sa_sigaction;
|
2014-05-29 14:27:53 +00:00
|
|
|
else
|
2017-06-08 07:41:38 +00:00
|
|
|
handler = old.sa_handler;
|
|
|
|
ASSUME(handler != SIG_ERR);
|
|
|
|
return handler;
|
2002-01-21 07:44:06 +00:00
|
|
|
}
|
|
|
|
|
2007-11-30 14:49:45 +00:00
|
|
|
sighandler_t
|
2023-07-17 21:31:59 +09:00
|
|
|
ruby_posix_signal(int signum, sighandler_t handler)
|
2002-01-21 07:44:06 +00:00
|
|
|
{
|
2007-12-08 09:01:43 +00:00
|
|
|
return ruby_signal(signum, handler);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
2005-02-21 09:33:34 +00:00
|
|
|
|
2014-12-18 05:26:57 +00:00
|
|
|
#elif defined _WIN32
|
|
|
|
static inline sighandler_t
|
|
|
|
ruby_signal(int signum, sighandler_t handler)
|
|
|
|
{
|
|
|
|
if (signum == SIGKILL) {
|
|
|
|
errno = EINVAL;
|
|
|
|
return SIG_ERR;
|
|
|
|
}
|
|
|
|
return signal(signum, handler);
|
|
|
|
}
|
|
|
|
|
2005-02-21 09:33:34 +00:00
|
|
|
#else /* !POSIX_SIGNAL */
|
2010-12-29 01:07:26 +00:00
|
|
|
#define ruby_signal(sig,handler) (/* rb_trap_accept_nativethreads[(sig)] = 0,*/ signal((sig),(handler)))
|
2008-04-26 08:30:22 +00:00
|
|
|
#if 0 /* def HAVE_NATIVETHREAD */
|
2005-02-22 14:50:33 +00:00
|
|
|
static sighandler_t
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 10:44:21 +00:00
|
|
|
ruby_nativethread_signal(int signum, sighandler_t handler)
|
2005-02-22 14:50:33 +00:00
|
|
|
{
|
|
|
|
sighandler_t old;
|
|
|
|
|
|
|
|
old = signal(signum, handler);
|
|
|
|
rb_trap_accept_nativethreads[signum] = 1;
|
|
|
|
return old;
|
|
|
|
}
|
2005-02-21 09:33:34 +00:00
|
|
|
#endif
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
|
|
|
|
2014-05-10 16:10:32 +00:00
|
|
|
static int
|
|
|
|
signal_ignored(int sig)
|
|
|
|
{
|
2014-10-06 07:23:06 +00:00
|
|
|
sighandler_t func;
|
2014-05-10 16:10:32 +00:00
|
|
|
#ifdef POSIX_SIGNAL
|
|
|
|
struct sigaction old;
|
|
|
|
(void)VALGRIND_MAKE_MEM_DEFINED(&old, sizeof(old));
|
|
|
|
if (sigaction(sig, NULL, &old) < 0) return FALSE;
|
2014-10-06 07:23:06 +00:00
|
|
|
func = old.sa_handler;
|
2014-05-10 16:10:32 +00:00
|
|
|
#else
|
Get ractor message passing working with > 1 thread sending/receiving values in same ractor
Rework ractors so that any ractor action (Ractor.receive, Ractor#send, Ractor.yield, Ractor#take,
Ractor.select) will operate on the thread that called the action. It will put that thread to sleep if
it's a blocking function and it needs to put it to sleep, and the awakening action (Ractor.yield,
Ractor#send) will wake up the blocked thread.
Before this change every blocking ractor action was associated with the ractor struct and its fields.
If a ractor called Ractor.receive, its wait status was wait_receiving, and when another ractor calls
r.send on it, it will look for that status in the ractor struct fields and wake it up. The problem was that
what if 2 threads call blocking ractor actions in the same ractor. Imagine if 1 thread has called Ractor.receive
and another r.take. Then, when a different ractor calls r.send on it, it doesn't know which ruby thread is associated
to which ractor action, so what ruby thread should it schedule? This change moves some fields onto the ruby thread
itself so that ruby threads are the ones that have ractor blocking statuses, and threads are then specifically scheduled
when unblocked.
Fixes [#17624]
Fixes [#21037]
2025-05-12 18:03:22 -04:00
|
|
|
// TODO: this is not a thread-safe way to do it. Needs lock.
|
2014-05-10 16:10:32 +00:00
|
|
|
sighandler_t old = signal(sig, SIG_DFL);
|
|
|
|
signal(sig, old);
|
2014-10-06 07:23:06 +00:00
|
|
|
func = old;
|
2014-05-10 16:10:32 +00:00
|
|
|
#endif
|
2014-10-06 07:23:06 +00:00
|
|
|
if (func == SIG_IGN) return 1;
|
|
|
|
return func == sighandler ? 0 : -1;
|
2014-05-10 16:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
signal_enque(int sig)
|
1999-08-13 05:45:20 +00:00
|
|
|
{
|
2008-09-04 04:22:04 +00:00
|
|
|
ATOMIC_INC(signal_buff.cnt[sig]);
|
|
|
|
ATOMIC_INC(signal_buff.size);
|
2014-05-10 16:10:32 +00:00
|
|
|
}
|
|
|
|
|
2020-12-12 16:06:19 +09:00
|
|
|
static void
|
2014-05-10 16:10:32 +00:00
|
|
|
sighandler(int sig)
|
|
|
|
{
|
2015-02-25 09:17:17 +00:00
|
|
|
int old_errnum = errno;
|
|
|
|
|
2023-05-15 23:14:51 +09:00
|
|
|
signal_enque(sig);
|
2023-03-14 20:07:59 +13:00
|
|
|
rb_thread_wakeup_timer_thread(sig);
|
2023-05-15 23:14:51 +09:00
|
|
|
|
2007-02-23 06:59:12 +00:00
|
|
|
#if !defined(BSD_SIGNAL) && !defined(POSIX_SIGNAL)
|
|
|
|
ruby_signal(sig, sighandler);
|
|
|
|
#endif
|
2015-02-25 09:17:17 +00:00
|
|
|
|
|
|
|
errno = old_errnum;
|
1999-08-13 05:45:20 +00:00
|
|
|
}
|
1999-01-20 04:59:39 +00:00
|
|
|
|
2009-01-01 21:50:01 +00:00
|
|
|
int
|
* cont.c (rb_fiber_current), dln.c (dln_print_undef, dln_undefined),
eval.c (rb_iterator_p, rb_need_block), load.c: (Init_load), ruby.c
(uscore_get, rb_f_chop), st.c (stat_col), signal.c
(rb_signal_buff_size, ruby_sig_finalize), thread.c
(rb_thread_sleep_forever, rb_thread_sleep_deadly, rb_thread_alone):
protoized.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21929 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-01 12:51:44 +00:00
|
|
|
rb_signal_buff_size(void)
|
2009-01-01 21:50:01 +00:00
|
|
|
{
|
2025-05-14 19:59:03 -07:00
|
|
|
return RUBY_ATOMIC_LOAD(signal_buff.size);
|
2009-01-01 21:50:01 +00:00
|
|
|
}
|
|
|
|
|
2011-07-10 17:04:40 +00:00
|
|
|
static void
|
2006-12-31 15:02:22 +00:00
|
|
|
rb_disable_interrupt(void)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2012-11-19 10:35:34 +00:00
|
|
|
#ifdef HAVE_PTHREAD_SIGMASK
|
2006-12-31 15:02:22 +00:00
|
|
|
sigset_t mask;
|
|
|
|
sigfillset(&mask);
|
|
|
|
pthread_sigmask(SIG_SETMASK, &mask, NULL);
|
2005-02-21 09:33:34 +00:00
|
|
|
#endif
|
2006-12-31 15:02:22 +00:00
|
|
|
}
|
2005-02-21 09:33:34 +00:00
|
|
|
|
2011-07-10 17:04:40 +00:00
|
|
|
static void
|
2006-12-31 15:02:22 +00:00
|
|
|
rb_enable_interrupt(void)
|
|
|
|
{
|
2012-11-19 10:35:34 +00:00
|
|
|
#ifdef HAVE_PTHREAD_SIGMASK
|
2006-12-31 15:02:22 +00:00
|
|
|
sigset_t mask;
|
|
|
|
sigemptyset(&mask);
|
|
|
|
pthread_sigmask(SIG_SETMASK, &mask, NULL);
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
2006-12-31 15:02:22 +00:00
|
|
|
}
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2006-12-31 15:02:22 +00:00
|
|
|
int
|
2008-09-04 04:22:04 +00:00
|
|
|
rb_get_next_signal(void)
|
2006-12-31 15:02:22 +00:00
|
|
|
{
|
|
|
|
int i, sig = 0;
|
|
|
|
|
2025-05-14 19:59:03 -07:00
|
|
|
if (rb_signal_buff_size() != 0) {
|
2011-06-30 22:29:34 +00:00
|
|
|
for (i=1; i<RUBY_NSIG; i++) {
|
|
|
|
if (signal_buff.cnt[i] > 0) {
|
2012-11-19 10:54:55 +00:00
|
|
|
ATOMIC_DEC(signal_buff.cnt[i]);
|
|
|
|
ATOMIC_DEC(signal_buff.size);
|
2011-06-30 22:29:34 +00:00
|
|
|
sig = i;
|
|
|
|
break;
|
2006-12-31 15:02:22 +00:00
|
|
|
}
|
|
|
|
}
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
2006-12-31 15:02:22 +00:00
|
|
|
return sig;
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2014-12-22 05:08:34 +00:00
|
|
|
#if defined SIGSEGV || defined SIGBUS || defined SIGILL || defined SIGFPE
|
|
|
|
static const char *received_signal;
|
2024-12-04 16:54:11 -05:00
|
|
|
# define clear_received_signal() do { \
|
|
|
|
if (GET_VM() != NULL) rb_gc_enable(); \
|
|
|
|
received_signal = 0; \
|
|
|
|
} while (0)
|
2014-12-22 05:08:34 +00:00
|
|
|
#else
|
|
|
|
# define clear_received_signal() ((void)0)
|
|
|
|
#endif
|
2013-02-21 07:34:53 +00:00
|
|
|
|
2013-11-21 06:33:41 +00:00
|
|
|
#if defined(USE_SIGALTSTACK) || defined(_WIN32)
|
2017-10-27 01:13:35 +00:00
|
|
|
NORETURN(void rb_ec_stack_overflow(rb_execution_context_t *ec, int crit));
|
2015-11-23 03:54:42 +00:00
|
|
|
# if defined __HAIKU__
|
|
|
|
# define USE_UCONTEXT_REG 1
|
|
|
|
# elif !(defined(HAVE_UCONTEXT_H) && (defined __i386__ || defined __x86_64__ || defined __amd64__))
|
2014-10-19 17:34:09 +00:00
|
|
|
# elif defined __linux__
|
|
|
|
# define USE_UCONTEXT_REG 1
|
|
|
|
# elif defined __APPLE__
|
|
|
|
# define USE_UCONTEXT_REG 1
|
2014-12-13 09:01:59 +00:00
|
|
|
# elif defined __FreeBSD__
|
|
|
|
# define USE_UCONTEXT_REG 1
|
2014-10-19 17:34:09 +00:00
|
|
|
# endif
|
2017-04-15 02:07:01 +00:00
|
|
|
#if defined(HAVE_PTHREAD_SIGMASK)
|
|
|
|
# define ruby_sigunmask pthread_sigmask
|
|
|
|
#elif defined(HAVE_SIGPROCMASK)
|
|
|
|
# define ruby_sigunmask sigprocmask
|
|
|
|
#endif
|
2017-04-14 12:59:59 +00:00
|
|
|
static void
|
2017-08-22 02:42:23 +00:00
|
|
|
reset_sigmask(int sig)
|
2017-04-14 12:59:59 +00:00
|
|
|
{
|
2017-04-15 02:07:01 +00:00
|
|
|
#if defined(ruby_sigunmask)
|
2017-04-14 12:59:59 +00:00
|
|
|
sigset_t mask;
|
2017-04-14 16:07:45 +00:00
|
|
|
#endif
|
2017-04-14 12:59:59 +00:00
|
|
|
clear_received_signal();
|
2017-04-15 02:07:01 +00:00
|
|
|
#if defined(ruby_sigunmask)
|
2017-04-14 12:59:59 +00:00
|
|
|
sigemptyset(&mask);
|
|
|
|
sigaddset(&mask, sig);
|
2017-04-15 02:07:01 +00:00
|
|
|
if (ruby_sigunmask(SIG_UNBLOCK, &mask, NULL)) {
|
|
|
|
rb_bug_errno(STRINGIZE(ruby_sigunmask)":unblock", errno);
|
|
|
|
}
|
2017-04-14 16:07:45 +00:00
|
|
|
#endif
|
2017-04-14 12:59:59 +00:00
|
|
|
}
|
|
|
|
|
2014-10-19 17:34:09 +00:00
|
|
|
# ifdef USE_UCONTEXT_REG
|
2014-04-04 08:37:25 +00:00
|
|
|
static void
|
2017-04-14 12:59:59 +00:00
|
|
|
check_stack_overflow(int sig, const uintptr_t addr, const ucontext_t *ctx)
|
2014-04-04 08:37:25 +00:00
|
|
|
{
|
2014-12-13 08:59:54 +00:00
|
|
|
const DEFINE_MCONTEXT_PTR(mctx, ctx);
|
2014-05-18 07:38:54 +00:00
|
|
|
# if defined __linux__
|
|
|
|
# if defined REG_RSP
|
|
|
|
const greg_t sp = mctx->gregs[REG_RSP];
|
2016-11-27 11:22:42 +00:00
|
|
|
const greg_t bp = mctx->gregs[REG_RBP];
|
2014-05-18 07:38:54 +00:00
|
|
|
# else
|
|
|
|
const greg_t sp = mctx->gregs[REG_ESP];
|
2016-11-27 11:22:42 +00:00
|
|
|
const greg_t bp = mctx->gregs[REG_EBP];
|
2014-05-18 07:38:54 +00:00
|
|
|
# endif
|
|
|
|
# elif defined __APPLE__
|
2024-09-26 10:32:30 +09:00
|
|
|
# include <AvailabilityMacros.h>
|
|
|
|
# if defined(MAC_OS_X_VERSION_10_5) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
2018-09-22 20:13:08 +00:00
|
|
|
# define MCTX_SS_REG(reg) __ss.__##reg
|
|
|
|
# else
|
|
|
|
# define MCTX_SS_REG(reg) ss.reg
|
|
|
|
# endif
|
2014-05-18 07:38:54 +00:00
|
|
|
# if defined(__LP64__)
|
2018-09-22 20:13:08 +00:00
|
|
|
const uintptr_t sp = mctx->MCTX_SS_REG(rsp);
|
|
|
|
const uintptr_t bp = mctx->MCTX_SS_REG(rbp);
|
2014-05-18 07:38:54 +00:00
|
|
|
# else
|
2018-09-22 20:13:08 +00:00
|
|
|
const uintptr_t sp = mctx->MCTX_SS_REG(esp);
|
|
|
|
const uintptr_t bp = mctx->MCTX_SS_REG(ebp);
|
2014-05-18 07:38:54 +00:00
|
|
|
# endif
|
2014-12-13 09:01:59 +00:00
|
|
|
# elif defined __FreeBSD__
|
|
|
|
# if defined(__amd64__)
|
|
|
|
const __register_t sp = mctx->mc_rsp;
|
2016-11-27 11:22:42 +00:00
|
|
|
const __register_t bp = mctx->mc_rbp;
|
2014-12-13 09:01:59 +00:00
|
|
|
# else
|
|
|
|
const __register_t sp = mctx->mc_esp;
|
2016-11-27 11:22:42 +00:00
|
|
|
const __register_t bp = mctx->mc_ebp;
|
2014-12-13 09:01:59 +00:00
|
|
|
# endif
|
2015-11-23 03:54:42 +00:00
|
|
|
# elif defined __HAIKU__
|
|
|
|
# if defined(__amd64__)
|
|
|
|
const unsigned long sp = mctx->rsp;
|
2016-11-27 11:22:42 +00:00
|
|
|
const unsigned long bp = mctx->rbp;
|
2015-11-23 03:54:42 +00:00
|
|
|
# else
|
|
|
|
const unsigned long sp = mctx->esp;
|
2016-11-27 11:22:42 +00:00
|
|
|
const unsigned long bp = mctx->ebp;
|
2015-11-23 03:54:42 +00:00
|
|
|
# endif
|
2014-04-04 08:37:25 +00:00
|
|
|
# endif
|
|
|
|
enum {pagesize = 4096};
|
2014-05-12 01:35:09 +00:00
|
|
|
const uintptr_t sp_page = (uintptr_t)sp / pagesize;
|
2016-11-27 11:22:42 +00:00
|
|
|
const uintptr_t bp_page = (uintptr_t)bp / pagesize;
|
2014-05-12 01:35:09 +00:00
|
|
|
const uintptr_t fault_page = addr / pagesize;
|
|
|
|
|
|
|
|
/* SP in ucontext is not decremented yet when `push` failed, so
|
|
|
|
* the fault page can be the next. */
|
2016-11-27 11:22:42 +00:00
|
|
|
if (sp_page == fault_page || sp_page == fault_page + 1 ||
|
2018-09-21 10:19:14 +00:00
|
|
|
(sp_page <= fault_page && fault_page <= bp_page)) {
|
2017-10-27 01:13:35 +00:00
|
|
|
rb_execution_context_t *ec = GET_EC();
|
2017-08-22 02:46:16 +00:00
|
|
|
int crit = FALSE;
|
2021-08-18 14:09:29 +09:00
|
|
|
int uplevel = roomof(pagesize, sizeof(*ec->tag)) / 2; /* XXX: heuristic */
|
|
|
|
while ((uintptr_t)ec->tag->buf / pagesize <= fault_page + 1) {
|
2014-06-23 02:11:31 +00:00
|
|
|
/* drop the last tag if it is close to the fault,
|
|
|
|
* otherwise it can cause stack overflow again at the same
|
|
|
|
* place. */
|
2021-08-18 14:09:29 +09:00
|
|
|
if ((crit = (!ec->tag->prev || !--uplevel)) != FALSE) break;
|
2025-04-20 14:48:02 -04:00
|
|
|
rb_vm_tag_jmpbuf_deinit(&ec->tag->buf);
|
2017-10-27 01:13:35 +00:00
|
|
|
ec->tag = ec->tag->prev;
|
2014-06-23 02:11:31 +00:00
|
|
|
}
|
2017-08-22 02:42:23 +00:00
|
|
|
reset_sigmask(sig);
|
2025-04-24 11:01:42 +09:00
|
|
|
rb_ec_stack_overflow(ec, crit + 1);
|
2014-04-04 08:37:25 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-19 17:34:09 +00:00
|
|
|
# else
|
2013-02-21 07:34:53 +00:00
|
|
|
static void
|
2017-04-14 12:59:59 +00:00
|
|
|
check_stack_overflow(int sig, const void *addr)
|
2013-02-21 07:34:53 +00:00
|
|
|
{
|
|
|
|
int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
|
2017-10-27 06:01:21 +00:00
|
|
|
rb_thread_t *th = GET_THREAD();
|
|
|
|
if (ruby_stack_overflowed_p(th, addr)) {
|
2017-08-22 02:42:23 +00:00
|
|
|
reset_sigmask(sig);
|
2025-04-24 11:01:42 +09:00
|
|
|
rb_ec_stack_overflow(th->ec, 1);
|
2013-02-21 07:34:53 +00:00
|
|
|
}
|
|
|
|
}
|
2014-10-19 17:34:09 +00:00
|
|
|
# endif
|
2024-04-03 23:14:52 +09:00
|
|
|
|
2014-10-19 17:34:09 +00:00
|
|
|
# ifdef _WIN32
|
2017-04-14 12:59:59 +00:00
|
|
|
# define CHECK_STACK_OVERFLOW() check_stack_overflow(sig, 0)
|
2014-10-19 17:34:09 +00:00
|
|
|
# else
|
|
|
|
# define FAULT_ADDRESS info->si_addr
|
|
|
|
# ifdef USE_UCONTEXT_REG
|
2024-04-03 23:14:52 +09:00
|
|
|
# define CHECK_STACK_OVERFLOW_() check_stack_overflow(sig, (uintptr_t)FAULT_ADDRESS, ctx)
|
2014-10-19 17:34:09 +00:00
|
|
|
# else
|
2024-04-03 23:14:52 +09:00
|
|
|
# define CHECK_STACK_OVERFLOW_() check_stack_overflow(sig, FAULT_ADDRESS)
|
2014-10-19 17:34:09 +00:00
|
|
|
# endif
|
|
|
|
# define MESSAGE_FAULT_ADDRESS " at %p", FAULT_ADDRESS
|
2024-04-03 23:14:52 +09:00
|
|
|
# define SIGNAL_FROM_USER_P() ((info)->si_code == SI_USER)
|
|
|
|
# define CHECK_STACK_OVERFLOW() (SIGNAL_FROM_USER_P() ? (void)0 : CHECK_STACK_OVERFLOW_())
|
2014-10-19 17:34:09 +00:00
|
|
|
# endif
|
2013-02-21 07:34:53 +00:00
|
|
|
#else
|
2014-10-19 17:34:09 +00:00
|
|
|
# define CHECK_STACK_OVERFLOW() (void)0
|
2013-02-21 07:34:53 +00:00
|
|
|
#endif
|
2013-12-03 03:18:49 +00:00
|
|
|
#ifndef MESSAGE_FAULT_ADDRESS
|
2014-10-19 17:34:09 +00:00
|
|
|
# define MESSAGE_FAULT_ADDRESS
|
2013-12-03 03:18:49 +00:00
|
|
|
#endif
|
2013-02-21 07:34:53 +00:00
|
|
|
|
2014-10-16 08:15:46 +00:00
|
|
|
#if defined SIGSEGV || defined SIGBUS || defined SIGILL || defined SIGFPE
|
2023-07-18 00:07:58 +09:00
|
|
|
NOINLINE(static void check_reserved_signal_(const char *name, size_t name_len, int signo));
|
2014-10-17 05:14:14 +00:00
|
|
|
/* noinine to reduce stack usage in signal handers */
|
|
|
|
|
2023-07-18 00:07:58 +09:00
|
|
|
#define check_reserved_signal(name) check_reserved_signal_(name, sizeof(name)-1, sig)
|
2014-10-16 08:15:46 +00:00
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
#ifdef SIGBUS
|
2018-01-18 09:44:43 +00:00
|
|
|
|
2019-10-09 23:13:59 +09:00
|
|
|
static sighandler_t default_sigbus_handler;
|
2018-01-18 09:44:43 +00:00
|
|
|
NORETURN(static ruby_sigaction_t sigbus);
|
|
|
|
|
2020-12-12 16:06:19 +09:00
|
|
|
static void
|
2011-07-02 19:59:05 +00:00
|
|
|
sigbus(int sig SIGINFO_ARG)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2014-10-16 08:15:46 +00:00
|
|
|
check_reserved_signal("BUS");
|
2011-07-02 19:59:05 +00:00
|
|
|
/*
|
|
|
|
* Mac OS X makes KERN_PROTECTION_FAILURE when thread touch guard page.
|
2013-04-09 00:24:24 +00:00
|
|
|
* and it's delivered as SIGBUS instead of SIGSEGV to userland. It's crazy
|
2011-07-02 19:59:05 +00:00
|
|
|
* wrong IMHO. but anyway we have to care it. Sigh.
|
|
|
|
*/
|
2015-02-01 00:29:02 +00:00
|
|
|
/* Seems Linux also delivers SIGBUS. */
|
|
|
|
#if defined __APPLE__ || defined __linux__
|
2013-02-21 07:34:53 +00:00
|
|
|
CHECK_STACK_OVERFLOW();
|
2011-07-02 19:59:05 +00:00
|
|
|
#endif
|
2019-10-09 23:13:59 +09:00
|
|
|
rb_bug_for_fatal_signal(default_sigbus_handler, sig, SIGINFO_CTX, "Bus Error" MESSAGE_FAULT_ADDRESS);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2014-10-16 08:15:46 +00:00
|
|
|
#ifdef SIGSEGV
|
2018-01-18 09:44:44 +00:00
|
|
|
|
2019-10-09 23:13:59 +09:00
|
|
|
static sighandler_t default_sigsegv_handler;
|
2018-01-18 09:44:44 +00:00
|
|
|
NORETURN(static ruby_sigaction_t sigsegv);
|
|
|
|
|
2020-12-12 16:06:19 +09:00
|
|
|
static void
|
2008-11-27 06:05:07 +00:00
|
|
|
sigsegv(int sig SIGINFO_ARG)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2014-10-16 08:15:46 +00:00
|
|
|
check_reserved_signal("SEGV");
|
|
|
|
CHECK_STACK_OVERFLOW();
|
2019-10-09 23:13:59 +09:00
|
|
|
rb_bug_for_fatal_signal(default_sigsegv_handler, sig, SIGINFO_CTX, "Segmentation fault" MESSAGE_FAULT_ADDRESS);
|
2014-10-16 08:15:46 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef SIGILL
|
2018-01-18 09:44:45 +00:00
|
|
|
|
2019-10-09 23:13:59 +09:00
|
|
|
static sighandler_t default_sigill_handler;
|
2018-01-18 09:44:45 +00:00
|
|
|
NORETURN(static ruby_sigaction_t sigill);
|
|
|
|
|
2020-12-12 16:06:19 +09:00
|
|
|
static void
|
2014-10-16 08:15:46 +00:00
|
|
|
sigill(int sig SIGINFO_ARG)
|
|
|
|
{
|
|
|
|
check_reserved_signal("ILL");
|
2021-08-18 14:11:34 +09:00
|
|
|
#if defined __APPLE__ || defined __linux__
|
2014-10-16 08:15:46 +00:00
|
|
|
CHECK_STACK_OVERFLOW();
|
|
|
|
#endif
|
2019-10-09 23:13:59 +09:00
|
|
|
rb_bug_for_fatal_signal(default_sigill_handler, sig, SIGINFO_CTX, "Illegal instruction" MESSAGE_FAULT_ADDRESS);
|
2014-10-16 08:15:46 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2019-10-09 22:57:19 +09:00
|
|
|
#ifndef __sun
|
|
|
|
NORETURN(static void ruby_abort(void));
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void
|
|
|
|
ruby_abort(void)
|
|
|
|
{
|
|
|
|
#ifdef __sun
|
|
|
|
/* Solaris's abort() is async signal unsafe. Of course, it is not
|
|
|
|
* POSIX compliant.
|
|
|
|
*/
|
|
|
|
raise(SIGABRT);
|
|
|
|
#else
|
|
|
|
abort();
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-10-16 08:15:46 +00:00
|
|
|
static void
|
2023-07-18 00:07:58 +09:00
|
|
|
check_reserved_signal_(const char *name, size_t name_len, int signo)
|
2014-10-16 08:15:46 +00:00
|
|
|
{
|
2014-12-21 02:35:44 +00:00
|
|
|
const char *prev = ATOMIC_PTR_EXCHANGE(received_signal, name);
|
2014-10-16 08:15:46 +00:00
|
|
|
|
|
|
|
if (prev) {
|
2013-02-24 01:16:46 +00:00
|
|
|
ssize_t RB_UNUSED_VAR(err);
|
2023-07-18 00:06:57 +09:00
|
|
|
static const int stderr_fd = 2;
|
2025-04-30 18:35:25 +09:00
|
|
|
#define NOZ(name, str) RBIMPL_ATTR_NONSTRING() name[sizeof(str)-1] = str
|
2014-10-17 05:14:02 +00:00
|
|
|
static const char NOZ(msg1, " received in ");
|
|
|
|
static const char NOZ(msg2, " handler\n");
|
2013-02-24 00:17:29 +00:00
|
|
|
|
2014-10-17 05:14:14 +00:00
|
|
|
#ifdef HAVE_WRITEV
|
|
|
|
struct iovec iov[4];
|
2023-07-18 00:06:57 +09:00
|
|
|
int i = 0;
|
|
|
|
# define W(str, len) \
|
|
|
|
iov[i++] = (struct iovec){.iov_base = (void *)(str), .iov_len = (len)}
|
2014-10-17 05:14:14 +00:00
|
|
|
#else
|
2023-07-18 00:06:57 +09:00
|
|
|
# define W(str, len) err = write(stderr_fd, (str), (len))
|
|
|
|
#endif
|
|
|
|
|
2023-07-18 00:07:58 +09:00
|
|
|
#if __has_feature(address_sanitizer) || \
|
|
|
|
__has_feature(memory_sanitizer) || \
|
|
|
|
defined(HAVE_VALGRIND_MEMCHECK_H)
|
|
|
|
ruby_posix_signal(signo, SIG_DFL);
|
|
|
|
#endif
|
2023-07-18 00:06:57 +09:00
|
|
|
W(name, name_len);
|
|
|
|
W(msg1, sizeof(msg1));
|
|
|
|
W(prev, strlen(prev));
|
|
|
|
W(msg2, sizeof(msg2));
|
|
|
|
# undef W
|
|
|
|
#ifdef HAVE_WRITEV
|
|
|
|
err = writev(stderr_fd, iov, i);
|
2014-10-17 05:14:14 +00:00
|
|
|
#endif
|
2013-02-21 05:18:38 +00:00
|
|
|
ruby_abort();
|
|
|
|
}
|
|
|
|
|
2024-12-04 16:54:11 -05:00
|
|
|
if (GET_VM() != NULL) {
|
|
|
|
rb_gc_disable_no_rest();
|
|
|
|
}
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2015-07-26 05:37:59 +00:00
|
|
|
#if defined SIGPIPE || defined SIGSYS
|
2020-12-12 16:06:19 +09:00
|
|
|
static void
|
2015-07-26 02:29:03 +00:00
|
|
|
sig_do_nothing(int sig)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-08-18 09:07:36 +00:00
|
|
|
static int
|
2019-09-20 19:06:22 -07:00
|
|
|
signal_exec(VALUE cmd, int sig)
|
2007-05-29 17:08:37 +00:00
|
|
|
{
|
2017-11-06 07:44:28 +00:00
|
|
|
rb_execution_context_t *ec = GET_EC();
|
2018-05-15 10:51:07 +00:00
|
|
|
volatile rb_atomic_t old_interrupt_mask = ec->interrupt_mask;
|
2017-06-23 07:25:52 +00:00
|
|
|
enum ruby_tag_type state;
|
2012-11-26 08:05:49 +00:00
|
|
|
|
2014-05-28 00:53:11 +00:00
|
|
|
/*
|
|
|
|
* workaround the following race:
|
|
|
|
* 1. signal_enque queues signal for execution
|
|
|
|
* 2. user calls trap(sig, "IGNORE"), setting SIG_IGN
|
|
|
|
* 3. rb_signal_exec runs on queued signal
|
|
|
|
*/
|
|
|
|
if (IMMEDIATE_P(cmd))
|
2018-08-18 09:07:36 +00:00
|
|
|
return FALSE;
|
2014-05-28 00:53:11 +00:00
|
|
|
|
2017-11-06 07:44:28 +00:00
|
|
|
ec->interrupt_mask |= TRAP_INTERRUPT_MASK;
|
|
|
|
EC_PUSH_TAG(ec);
|
2017-12-06 03:16:08 +00:00
|
|
|
if ((state = EC_EXEC_TAG()) == TAG_NONE) {
|
2012-11-26 09:25:47 +00:00
|
|
|
VALUE signum = INT2NUM(sig);
|
2019-09-25 15:49:21 -07:00
|
|
|
rb_eval_cmd_kw(cmd, rb_ary_new3(1, signum), RB_NO_KEYWORDS);
|
2012-11-26 08:05:49 +00:00
|
|
|
}
|
2017-10-26 11:02:13 +00:00
|
|
|
EC_POP_TAG();
|
2017-11-06 07:44:28 +00:00
|
|
|
ec = GET_EC();
|
|
|
|
ec->interrupt_mask = old_interrupt_mask;
|
2012-11-26 08:05:49 +00:00
|
|
|
|
|
|
|
if (state) {
|
2012-12-23 10:18:58 +00:00
|
|
|
/* XXX: should be replaced with rb_threadptr_pending_interrupt_enque() */
|
2017-11-06 07:44:28 +00:00
|
|
|
EC_JUMP_TAG(ec, state);
|
2012-11-26 08:05:49 +00:00
|
|
|
}
|
2018-08-18 09:07:36 +00:00
|
|
|
return TRUE;
|
2007-05-29 17:08:37 +00:00
|
|
|
}
|
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
void
|
2019-08-12 17:44:30 +09:00
|
|
|
rb_vm_trap_exit(rb_vm_t *vm)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2017-07-27 12:17:56 +00:00
|
|
|
VALUE trap_exit = vm->trap_list.cmd[0];
|
2000-11-27 09:23:38 +00:00
|
|
|
|
2008-09-04 04:22:04 +00:00
|
|
|
if (trap_exit) {
|
2017-07-27 12:17:56 +00:00
|
|
|
vm->trap_list.cmd[0] = 0;
|
2019-09-20 19:06:22 -07:00
|
|
|
signal_exec(trap_exit, 0);
|
1999-01-20 04:59:39 +00:00
|
|
|
}
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2018-08-18 09:07:36 +00:00
|
|
|
/* returns true if a trap handler was run, false otherwise */
|
|
|
|
int
|
* blockinlining.c, error.c, eval.c, eval_error.h, eval_intern.h,
eval_jump.h, eval_load.c, eval_safe.h, gc.c, proc.c, signal.c,
thread.c, thread_pthread.ci, thread_win32.ci, vm.c, vm.h,
vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fix typo (rb_thead_t -> rb_thread_t).
* eval_intern.h: remove unused definitions.
* common.mk: fix around vm_opts.h path
and remove harmful argument passed to insns2vm.rb.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11658 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-08 06:37:46 +00:00
|
|
|
rb_signal_exec(rb_thread_t *th, int sig)
|
2006-12-31 15:02:22 +00:00
|
|
|
{
|
2008-09-04 04:22:04 +00:00
|
|
|
rb_vm_t *vm = GET_VM();
|
2017-07-27 12:17:56 +00:00
|
|
|
VALUE cmd = vm->trap_list.cmd[sig];
|
2006-12-31 15:02:22 +00:00
|
|
|
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
if (cmd == 0) {
|
|
|
|
switch (sig) {
|
|
|
|
case SIGINT:
|
|
|
|
rb_interrupt();
|
|
|
|
break;
|
2006-12-31 15:02:22 +00:00
|
|
|
#ifdef SIGHUP
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
case SIGHUP:
|
2006-12-31 15:02:22 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGQUIT
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
case SIGQUIT:
|
2006-12-31 15:02:22 +00:00
|
|
|
#endif
|
2007-04-19 17:37:03 +00:00
|
|
|
#ifdef SIGTERM
|
|
|
|
case SIGTERM:
|
|
|
|
#endif
|
2006-12-31 15:02:22 +00:00
|
|
|
#ifdef SIGALRM
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
case SIGALRM:
|
2006-12-31 15:02:22 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR1
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
case SIGUSR1:
|
2006-12-31 15:02:22 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR2
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
case SIGUSR2:
|
2006-12-31 15:02:22 +00:00
|
|
|
#endif
|
2009-06-08 16:14:06 +00:00
|
|
|
rb_threadptr_signal_raise(th, sig);
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2022-11-15 13:24:08 +09:00
|
|
|
else if (UNDEF_P(cmd)) {
|
2009-06-08 16:14:06 +00:00
|
|
|
rb_threadptr_signal_exit(th);
|
* call_cfunc.ci, compile.c, compile.h, debug.h, eval.c,
eval_error.h, eval_jump.h, eval_load.c, eval_thread.c, gc.c,
insnhelper.h, insns.def, iseq.c, main.c, numeric.c, parse.y,
range.c, regenc.h, ruby.h, signal.c, thread.c, thread_win32.ci,
vm.c, vm.h, vm_dump.c, vm_evalbody.ci, yarvcore.c, yarvcore.h:
fixed indents and non-C90 comments.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@11620 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2007-02-02 16:26:04 +00:00
|
|
|
}
|
|
|
|
else {
|
2019-09-20 19:06:22 -07:00
|
|
|
return signal_exec(cmd, sig);
|
2006-12-31 15:02:22 +00:00
|
|
|
}
|
2018-08-18 09:07:36 +00:00
|
|
|
return FALSE;
|
2006-12-31 15:02:22 +00:00
|
|
|
}
|
|
|
|
|
2007-06-15 13:38:32 +00:00
|
|
|
static sighandler_t
|
|
|
|
default_handler(int sig)
|
|
|
|
{
|
|
|
|
sighandler_t func;
|
|
|
|
switch (sig) {
|
|
|
|
case SIGINT:
|
|
|
|
#ifdef SIGHUP
|
|
|
|
case SIGHUP:
|
|
|
|
#endif
|
|
|
|
#ifdef SIGQUIT
|
|
|
|
case SIGQUIT:
|
|
|
|
#endif
|
|
|
|
#ifdef SIGTERM
|
|
|
|
case SIGTERM:
|
|
|
|
#endif
|
|
|
|
#ifdef SIGALRM
|
|
|
|
case SIGALRM:
|
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR1
|
|
|
|
case SIGUSR1:
|
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR2
|
|
|
|
case SIGUSR2:
|
2023-05-16 12:49:06 +09:00
|
|
|
#endif
|
|
|
|
#ifdef RUBY_SIGCHLD
|
|
|
|
case RUBY_SIGCHLD:
|
2007-06-15 13:38:32 +00:00
|
|
|
#endif
|
|
|
|
func = sighandler;
|
|
|
|
break;
|
|
|
|
#ifdef SIGBUS
|
|
|
|
case SIGBUS:
|
2011-07-02 19:59:05 +00:00
|
|
|
func = (sighandler_t)sigbus;
|
2007-06-15 13:38:32 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef SIGSEGV
|
|
|
|
case SIGSEGV:
|
2008-11-27 06:05:07 +00:00
|
|
|
func = (sighandler_t)sigsegv;
|
2007-06-15 13:38:32 +00:00
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef SIGPIPE
|
|
|
|
case SIGPIPE:
|
2015-07-26 05:37:59 +00:00
|
|
|
func = sig_do_nothing;
|
2007-06-15 13:38:32 +00:00
|
|
|
break;
|
2015-07-26 02:29:03 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGSYS
|
|
|
|
case SIGSYS:
|
|
|
|
func = sig_do_nothing;
|
|
|
|
break;
|
2007-06-15 13:38:32 +00:00
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
func = SIG_DFL;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return func;
|
|
|
|
}
|
|
|
|
|
2007-05-29 17:08:37 +00:00
|
|
|
static sighandler_t
|
2007-06-15 13:38:32 +00:00
|
|
|
trap_handler(VALUE *cmd, int sig)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2008-07-16 09:04:37 +00:00
|
|
|
sighandler_t func = sighandler;
|
2007-05-29 17:08:37 +00:00
|
|
|
VALUE command;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2007-05-29 17:08:37 +00:00
|
|
|
if (NIL_P(*cmd)) {
|
1998-01-16 12:13:05 +00:00
|
|
|
func = SIG_IGN;
|
|
|
|
}
|
2005-06-30 06:20:09 +00:00
|
|
|
else {
|
2007-05-29 17:08:37 +00:00
|
|
|
command = rb_check_string_type(*cmd);
|
2009-01-23 04:25:29 +00:00
|
|
|
if (NIL_P(command) && SYMBOL_P(*cmd)) {
|
2014-07-28 08:15:42 +00:00
|
|
|
command = rb_sym2str(*cmd);
|
2009-01-23 04:25:29 +00:00
|
|
|
if (!command) rb_raise(rb_eArgError, "bad handler");
|
|
|
|
}
|
2005-06-30 06:20:09 +00:00
|
|
|
if (!NIL_P(command)) {
|
2015-07-17 22:08:49 +00:00
|
|
|
const char *cptr;
|
|
|
|
long len;
|
2019-09-24 20:59:12 -07:00
|
|
|
StringValue(command);
|
2008-07-16 09:04:37 +00:00
|
|
|
*cmd = command;
|
2015-07-17 22:08:49 +00:00
|
|
|
RSTRING_GETMEM(command, cptr, len);
|
|
|
|
switch (len) {
|
2020-06-17 14:28:54 +09:00
|
|
|
sig_ign:
|
|
|
|
func = SIG_IGN;
|
|
|
|
*cmd = Qtrue;
|
|
|
|
break;
|
|
|
|
sig_dfl:
|
|
|
|
func = default_handler(sig);
|
|
|
|
*cmd = 0;
|
|
|
|
break;
|
2005-06-30 06:20:09 +00:00
|
|
|
case 0:
|
2007-06-15 13:38:32 +00:00
|
|
|
goto sig_ign;
|
2005-06-30 06:20:09 +00:00
|
|
|
break;
|
2007-06-15 13:38:32 +00:00
|
|
|
case 14:
|
2015-07-17 22:08:49 +00:00
|
|
|
if (memcmp(cptr, "SYSTEM_DEFAULT", 14) == 0) {
|
2007-06-15 13:38:32 +00:00
|
|
|
func = SIG_DFL;
|
|
|
|
*cmd = 0;
|
|
|
|
}
|
|
|
|
break;
|
2005-06-30 06:20:09 +00:00
|
|
|
case 7:
|
2015-07-17 22:08:49 +00:00
|
|
|
if (memcmp(cptr, "SIG_IGN", 7) == 0) {
|
2020-06-17 14:28:54 +09:00
|
|
|
goto sig_ign;
|
2005-06-30 06:20:09 +00:00
|
|
|
}
|
2015-07-17 22:08:49 +00:00
|
|
|
else if (memcmp(cptr, "SIG_DFL", 7) == 0) {
|
2020-06-17 14:28:54 +09:00
|
|
|
goto sig_dfl;
|
2005-06-30 06:20:09 +00:00
|
|
|
}
|
2015-07-17 22:08:49 +00:00
|
|
|
else if (memcmp(cptr, "DEFAULT", 7) == 0) {
|
2007-06-15 13:38:32 +00:00
|
|
|
goto sig_dfl;
|
2005-06-30 06:20:09 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 6:
|
2015-07-17 22:08:49 +00:00
|
|
|
if (memcmp(cptr, "IGNORE", 6) == 0) {
|
2007-06-15 13:38:32 +00:00
|
|
|
goto sig_ign;
|
2005-06-30 06:20:09 +00:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case 4:
|
2015-07-17 22:08:49 +00:00
|
|
|
if (memcmp(cptr, "EXIT", 4) == 0) {
|
2007-05-29 17:08:37 +00:00
|
|
|
*cmd = Qundef;
|
2005-06-30 06:20:09 +00:00
|
|
|
}
|
|
|
|
break;
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
2007-05-29 17:08:37 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
rb_proc_t *proc;
|
|
|
|
GetProcPtr(*cmd, proc);
|
* bignum.c (big_rshift), compile.c (validate_label,
iseq_build_from_ary_exception), cont.c (cont_capture), dir.c
(dir_open_dir), gc.c (objspace_each_objects), io.c (pipe_open)
(rb_io_advise), parse.y (parser_compile_string)
(rb_parser_compile_file), proc.c (binding_free), process.c
(rb_proc_exec_n, rb_seteuid_core, proc_setegid, rb_setegid_core)
(p_uid_exchange, p_gid_exchange), regparse.c (strdup_with_null),
signal.c (sig_dfl), vm.c (rb_iseq_eval, rb_iseq_eval_main),
vm_insnhelper.c (vm_expandarray): suppress
unused-but-set-variable warnings.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33951 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2011-12-05 09:57:00 +00:00
|
|
|
(void)proc;
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-05-29 17:08:37 +00:00
|
|
|
return func;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
trap_signm(VALUE vsig)
|
|
|
|
{
|
|
|
|
int sig = -1;
|
|
|
|
|
2018-03-10 10:36:35 +00:00
|
|
|
if (FIXNUM_P(vsig)) {
|
2007-05-29 17:08:37 +00:00
|
|
|
sig = FIX2INT(vsig);
|
|
|
|
if (sig < 0 || sig >= NSIG) {
|
|
|
|
rb_raise(rb_eArgError, "invalid signal number (%d)", sig);
|
|
|
|
}
|
2018-03-10 10:36:35 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-03-10 11:26:54 +00:00
|
|
|
sig = signm2signo(&vsig, FALSE, TRUE, NULL);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
2007-05-29 17:08:37 +00:00
|
|
|
return sig;
|
|
|
|
}
|
|
|
|
|
|
|
|
static VALUE
|
2012-11-19 10:35:34 +00:00
|
|
|
trap(int sig, sighandler_t func, VALUE command)
|
2007-05-29 17:08:37 +00:00
|
|
|
{
|
2012-11-19 10:35:34 +00:00
|
|
|
sighandler_t oldfunc;
|
|
|
|
VALUE oldcmd;
|
2008-09-04 04:22:04 +00:00
|
|
|
rb_vm_t *vm = GET_VM();
|
2007-05-29 17:08:37 +00:00
|
|
|
|
2012-11-19 10:35:34 +00:00
|
|
|
/*
|
2017-07-27 12:17:56 +00:00
|
|
|
* Be careful. ruby_signal() and trap_list.cmd[sig] must be changed
|
2012-11-19 10:35:34 +00:00
|
|
|
* atomically. In current implementation, we only need to don't call
|
|
|
|
* RUBY_VM_CHECK_INTS().
|
|
|
|
*/
|
2014-09-21 05:10:14 +00:00
|
|
|
if (sig == 0) {
|
|
|
|
oldfunc = SIG_ERR;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
oldfunc = ruby_signal(sig, func);
|
|
|
|
if (oldfunc == SIG_ERR) rb_sys_fail_str(rb_signo2signm(sig));
|
|
|
|
}
|
2017-07-27 12:17:56 +00:00
|
|
|
oldcmd = vm->trap_list.cmd[sig];
|
2007-05-29 17:08:37 +00:00
|
|
|
switch (oldcmd) {
|
|
|
|
case 0:
|
2014-05-28 00:53:11 +00:00
|
|
|
case Qtrue:
|
2003-03-25 15:25:18 +00:00
|
|
|
if (oldfunc == SIG_IGN) oldcmd = rb_str_new2("IGNORE");
|
2014-05-09 23:48:47 +00:00
|
|
|
else if (oldfunc == SIG_DFL) oldcmd = rb_str_new2("SYSTEM_DEFAULT");
|
2003-03-25 15:25:18 +00:00
|
|
|
else if (oldfunc == sighandler) oldcmd = rb_str_new2("DEFAULT");
|
|
|
|
else oldcmd = Qnil;
|
2007-05-29 17:08:37 +00:00
|
|
|
break;
|
2014-05-28 00:53:11 +00:00
|
|
|
case Qnil:
|
|
|
|
break;
|
2007-05-29 17:08:37 +00:00
|
|
|
case Qundef:
|
|
|
|
oldcmd = rb_str_new2("EXIT");
|
|
|
|
break;
|
2003-03-25 15:25:18 +00:00
|
|
|
}
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2018-07-05 03:02:33 +00:00
|
|
|
ACCESS_ONCE(VALUE, vm->trap_list.cmd[sig]) = command;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2012-11-19 10:35:34 +00:00
|
|
|
return oldcmd;
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2011-12-05 05:33:49 +00:00
|
|
|
static int
|
|
|
|
reserved_signal_p(int signo)
|
2011-07-12 04:55:50 +00:00
|
|
|
{
|
|
|
|
/* Synchronous signal can't deliver to main thread */
|
|
|
|
#ifdef SIGSEGV
|
|
|
|
if (signo == SIGSEGV)
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef SIGBUS
|
|
|
|
if (signo == SIGBUS)
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef SIGILL
|
|
|
|
if (signo == SIGILL)
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
#ifdef SIGFPE
|
|
|
|
if (signo == SIGFPE)
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* used ubf internal see thread_pthread.c. */
|
|
|
|
#ifdef SIGVTALRM
|
|
|
|
if (signo == SIGVTALRM)
|
|
|
|
return 1;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2003-12-27 16:07:43 +00:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 21:07:33 +00:00
|
|
|
* Signal.trap( signal, command ) -> obj
|
|
|
|
* Signal.trap( signal ) {| | block } -> obj
|
2003-12-27 16:07:43 +00:00
|
|
|
*
|
|
|
|
* 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
|
2007-06-15 14:33:59 +00:00
|
|
|
* signal is raised.
|
|
|
|
* If the command is the string ``IGNORE'' or ``SIG_IGN'', the signal
|
|
|
|
* will be ignored.
|
|
|
|
* If the command is ``DEFAULT'' or ``SIG_DFL'', the Ruby's default handler
|
|
|
|
* will be invoked.
|
|
|
|
* If the command is ``EXIT'', the script will be terminated by the signal.
|
2007-06-15 13:38:32 +00:00
|
|
|
* If the command is ``SYSTEM_DEFAULT'', the operating system's default
|
|
|
|
* handler will be invoked.
|
2007-06-15 14:33:59 +00:00
|
|
|
* Otherwise, the given command or block will be run.
|
2003-12-27 16:07:43 +00:00
|
|
|
* The special signal name ``EXIT'' or signal number zero will be
|
|
|
|
* invoked just prior to program termination.
|
|
|
|
* trap returns the previous handler for the given signal.
|
|
|
|
*
|
|
|
|
* Signal.trap(0, proc { puts "Terminating: #{$$}" })
|
|
|
|
* Signal.trap("CLD") { puts "Child died" }
|
|
|
|
* fork && Process.wait
|
|
|
|
*
|
2023-01-01 14:33:06 +09:00
|
|
|
* <em>produces:</em>
|
2003-12-27 16:07:43 +00:00
|
|
|
* Terminating: 27461
|
|
|
|
* Child died
|
|
|
|
* Terminating: 27460
|
|
|
|
*/
|
1998-01-16 12:13:05 +00:00
|
|
|
static VALUE
|
2019-08-28 17:48:48 +09:00
|
|
|
sig_trap(int argc, VALUE *argv, VALUE _)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2012-11-19 10:35:34 +00:00
|
|
|
int sig;
|
|
|
|
sighandler_t func;
|
|
|
|
VALUE cmd;
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2012-03-14 21:10:34 +00:00
|
|
|
rb_check_arity(argc, 1, 2);
|
1998-01-16 12:13:05 +00:00
|
|
|
|
2012-11-19 10:35:34 +00:00
|
|
|
sig = trap_signm(argv[0]);
|
|
|
|
if (reserved_signal_p(sig)) {
|
|
|
|
const char *name = signo2signm(sig);
|
2012-02-23 10:57:55 +00:00
|
|
|
if (name)
|
|
|
|
rb_raise(rb_eArgError, "can't trap reserved signal: SIG%s", name);
|
|
|
|
else
|
2012-11-19 10:35:34 +00:00
|
|
|
rb_raise(rb_eArgError, "can't trap reserved signal: %d", sig);
|
2011-07-12 04:55:50 +00:00
|
|
|
}
|
|
|
|
|
1998-01-16 12:13:05 +00:00
|
|
|
if (argc == 1) {
|
2012-11-19 10:35:34 +00:00
|
|
|
cmd = rb_block_proc();
|
|
|
|
func = sighandler;
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
2009-03-10 19:22:11 +00:00
|
|
|
else {
|
2012-11-19 10:35:34 +00:00
|
|
|
cmd = argv[1];
|
|
|
|
func = trap_handler(&cmd, sig);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2020-12-12 06:54:46 +09:00
|
|
|
if (rb_obj_is_proc(cmd) &&
|
|
|
|
!rb_ractor_main_p() && !rb_ractor_shareable_p(cmd)) {
|
|
|
|
cmd = rb_proc_isolate(cmd);
|
|
|
|
}
|
|
|
|
|
2012-11-19 10:35:34 +00:00
|
|
|
return trap(sig, func, cmd);
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|
|
|
|
|
2003-12-27 16:07:43 +00:00
|
|
|
/*
|
|
|
|
* call-seq:
|
2010-05-17 21:07:33 +00:00
|
|
|
* Signal.list -> a_hash
|
2003-12-27 16:07:43 +00:00
|
|
|
*
|
|
|
|
* Returns a list of signal names mapped to the corresponding
|
|
|
|
* underlying signal numbers.
|
|
|
|
*
|
2008-06-10 23:23:36 +00:00
|
|
|
* 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}
|
2003-12-27 16:07:43 +00:00
|
|
|
*/
|
2001-08-23 06:02:15 +00:00
|
|
|
static VALUE
|
2019-08-28 17:48:48 +09:00
|
|
|
sig_list(VALUE _)
|
2001-08-23 06:02:15 +00:00
|
|
|
{
|
|
|
|
VALUE h = rb_hash_new();
|
2008-04-26 08:30:22 +00:00
|
|
|
const struct signals *sigs;
|
2001-08-23 06:02:15 +00:00
|
|
|
|
2018-07-04 16:10:14 +00:00
|
|
|
FOREACH_SIGNAL(sigs, 0) {
|
2016-01-26 05:33:28 +00:00
|
|
|
rb_hash_aset(h, rb_fstring_cstr(sigs->signm), INT2FIX(sigs->signo));
|
2001-08-23 06:02:15 +00:00
|
|
|
}
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
|
2017-06-09 13:02:13 +00:00
|
|
|
#define INSTALL_SIGHANDLER(cond, signame, signum) do { \
|
|
|
|
static const char failed[] = "failed to install "signame" handler"; \
|
|
|
|
if (!(cond)) break; \
|
|
|
|
if (reserved_signal_p(signum)) rb_bug(failed); \
|
|
|
|
perror(failed); \
|
|
|
|
} while (0)
|
2023-05-15 23:14:51 +09:00
|
|
|
|
2014-09-21 02:42:40 +00:00
|
|
|
static int
|
2019-10-09 23:13:59 +09:00
|
|
|
install_sighandler_core(int signum, sighandler_t handler, sighandler_t *old_handler)
|
2002-01-21 07:44:06 +00:00
|
|
|
{
|
|
|
|
sighandler_t old;
|
|
|
|
|
|
|
|
old = ruby_signal(signum, handler);
|
2014-09-21 02:42:40 +00:00
|
|
|
if (old == SIG_ERR) return -1;
|
2019-10-09 23:13:59 +09:00
|
|
|
if (old_handler) {
|
|
|
|
*old_handler = (old == SIG_DFL || old == SIG_IGN) ? 0 : old;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
/* signal handler should be inherited during exec. */
|
|
|
|
if (old != SIG_DFL) {
|
|
|
|
ruby_signal(signum, old);
|
|
|
|
}
|
2002-01-21 07:44:06 +00:00
|
|
|
}
|
2014-09-21 02:42:40 +00:00
|
|
|
return 0;
|
2002-01-21 07:44:06 +00:00
|
|
|
}
|
2017-10-23 05:56:25 +00:00
|
|
|
|
2017-06-08 07:41:38 +00:00
|
|
|
# define install_sighandler(signum, handler) \
|
2019-10-09 23:13:59 +09:00
|
|
|
INSTALL_SIGHANDLER(install_sighandler_core(signum, handler, NULL), #signum, signum)
|
|
|
|
# define force_install_sighandler(signum, handler, old_handler) \
|
|
|
|
INSTALL_SIGHANDLER(install_sighandler_core(signum, handler, old_handler), #signum, signum)
|
2002-01-21 07:44:06 +00:00
|
|
|
|
2007-11-30 14:08:58 +00:00
|
|
|
void
|
* cont.c (rb_fiber_current), dln.c (dln_print_undef, dln_undefined),
eval.c (rb_iterator_p, rb_need_block), load.c: (Init_load), ruby.c
(uscore_get, rb_f_chop), st.c (stat_col), signal.c
(rb_signal_buff_size, ruby_sig_finalize), thread.c
(rb_thread_sleep_forever, rb_thread_sleep_deadly, rb_thread_alone):
protoized.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@21929 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2009-02-01 12:51:44 +00:00
|
|
|
ruby_sig_finalize(void)
|
2007-11-30 14:08:58 +00:00
|
|
|
{
|
|
|
|
sighandler_t oldfunc;
|
|
|
|
|
|
|
|
oldfunc = ruby_signal(SIGINT, SIG_IGN);
|
|
|
|
if (oldfunc == sighandler) {
|
|
|
|
ruby_signal(SIGINT, SIG_DFL);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-29 07:57:24 +00:00
|
|
|
int ruby_enable_coredump = 0;
|
2007-06-28 14:22:30 +00:00
|
|
|
|
2003-12-27 16:07:43 +00:00
|
|
|
/*
|
|
|
|
* Many operating systems allow signals to be sent to running
|
|
|
|
* processes. Some signals have a defined effect on the process, while
|
|
|
|
* others may be trapped at the code level and acted upon. For
|
|
|
|
* example, your process may trap the USR1 signal and use it to toggle
|
|
|
|
* debugging, and may use TERM to initiate a controlled shutdown.
|
|
|
|
*
|
|
|
|
* pid = fork do
|
|
|
|
* Signal.trap("USR1") do
|
|
|
|
* $debug = !$debug
|
|
|
|
* puts "Debug now: #$debug"
|
|
|
|
* end
|
|
|
|
* Signal.trap("TERM") do
|
|
|
|
* puts "Terminating..."
|
|
|
|
* shutdown()
|
|
|
|
* end
|
|
|
|
* # . . . do some work . . .
|
|
|
|
* end
|
|
|
|
*
|
|
|
|
* Process.detach(pid)
|
|
|
|
*
|
|
|
|
* # Controlling program:
|
|
|
|
* Process.kill("USR1", pid)
|
|
|
|
* # ...
|
|
|
|
* Process.kill("USR1", pid)
|
|
|
|
* # ...
|
|
|
|
* Process.kill("TERM", pid)
|
|
|
|
*
|
2023-01-01 14:33:06 +09:00
|
|
|
* <em>produces:</em>
|
2003-12-27 16:07:43 +00:00
|
|
|
* Debug now: true
|
|
|
|
* Debug now: false
|
2023-01-01 14:33:06 +09:00
|
|
|
* Terminating...
|
2003-12-27 16:07:43 +00:00
|
|
|
*
|
|
|
|
* The list of available signal names and their interpretation is
|
|
|
|
* system dependent. Signal delivery semantics may also vary between
|
|
|
|
* systems; in particular signal delivery may not always be reliable.
|
|
|
|
*/
|
1998-01-16 12:13:05 +00:00
|
|
|
void
|
* array.c: moved to ANSI function style from K&R function style.
(used protoize on windows, so still K&R remains on #ifdef part of
other platforms. And `foo _((boo))' stuff is still there)
[ruby-dev:26975]
* bignum.c, class.c, compar.c, dir.c, dln.c, dmyext.c, enum.c,
enumerator.c, error.c, eval.c, file.c, gc.c, hash.c, inits.c,
io.c, main.c, marshal.c, math.c, numeric.c, object.c, pack.c,
prec.c, process.c, random.c, range.c, re.c, regcomp.c, regenc.c,
regerror.c, regexec.c, regparse.c, regparse.h, ruby.c, signal.c,
sprintf.c, st.c, string.c, struct.c, time.c, util.h, variable.c,
version.c: ditto.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@9126 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2005-09-12 10:44:21 +00:00
|
|
|
Init_signal(void)
|
1998-01-16 12:13:05 +00:00
|
|
|
{
|
2001-08-23 06:02:15 +00:00
|
|
|
VALUE mSignal = rb_define_module("Signal");
|
|
|
|
|
|
|
|
rb_define_global_function("trap", sig_trap, -1);
|
|
|
|
rb_define_module_function(mSignal, "trap", sig_trap, -1);
|
|
|
|
rb_define_module_function(mSignal, "list", sig_list, 0);
|
2012-11-19 09:43:53 +00:00
|
|
|
rb_define_module_function(mSignal, "signame", sig_signame, 1);
|
2001-08-23 06:02:15 +00:00
|
|
|
|
2007-04-19 17:37:03 +00:00
|
|
|
rb_define_method(rb_eSignal, "initialize", esignal_init, -1);
|
2008-05-30 13:32:39 +00:00
|
|
|
rb_define_method(rb_eSignal, "signo", esignal_signo, 0);
|
2014-07-03 03:38:10 +00:00
|
|
|
rb_alias(rb_eSignal, rb_intern_const("signm"), rb_intern_const("message"));
|
2007-04-19 17:37:03 +00:00
|
|
|
rb_define_method(rb_eInterrupt, "initialize", interrupt_init, -1);
|
|
|
|
|
2023-12-11 21:12:08 -08:00
|
|
|
// It should be ready to call rb_signal_exec()
|
|
|
|
VM_ASSERT(GET_THREAD()->pending_interrupt_queue);
|
|
|
|
|
2014-10-28 18:39:45 +00:00
|
|
|
/* At this time, there is no subthread. Then sigmask guarantee atomics. */
|
|
|
|
rb_disable_interrupt();
|
|
|
|
|
2002-01-21 07:44:06 +00:00
|
|
|
install_sighandler(SIGINT, sighandler);
|
2000-05-13 16:13:31 +00:00
|
|
|
#ifdef SIGHUP
|
2002-01-21 07:44:06 +00:00
|
|
|
install_sighandler(SIGHUP, sighandler);
|
1999-08-13 05:45:20 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGQUIT
|
2002-01-21 07:44:06 +00:00
|
|
|
install_sighandler(SIGQUIT, sighandler);
|
1999-08-13 05:45:20 +00:00
|
|
|
#endif
|
2006-10-18 13:59:19 +00:00
|
|
|
#ifdef SIGTERM
|
|
|
|
install_sighandler(SIGTERM, sighandler);
|
|
|
|
#endif
|
1999-08-13 05:45:20 +00:00
|
|
|
#ifdef SIGALRM
|
2002-01-21 07:44:06 +00:00
|
|
|
install_sighandler(SIGALRM, sighandler);
|
1999-08-13 05:45:20 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR1
|
2002-01-21 07:44:06 +00:00
|
|
|
install_sighandler(SIGUSR1, sighandler);
|
1999-08-13 05:45:20 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SIGUSR2
|
2002-01-21 07:44:06 +00:00
|
|
|
install_sighandler(SIGUSR2, sighandler);
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
1999-08-13 05:45:20 +00:00
|
|
|
|
2010-10-13 02:04:10 +00:00
|
|
|
if (!ruby_enable_coredump) {
|
1998-01-16 12:13:05 +00:00
|
|
|
#ifdef SIGBUS
|
2019-10-09 23:13:59 +09:00
|
|
|
force_install_sighandler(SIGBUS, (sighandler_t)sigbus, &default_sigbus_handler);
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
2014-10-16 08:15:46 +00:00
|
|
|
#ifdef SIGILL
|
2019-10-09 23:13:59 +09:00
|
|
|
force_install_sighandler(SIGILL, (sighandler_t)sigill, &default_sigill_handler);
|
2014-10-16 08:15:46 +00:00
|
|
|
#endif
|
1998-01-16 12:13:05 +00:00
|
|
|
#ifdef SIGSEGV
|
2020-03-06 21:32:42 +09:00
|
|
|
RB_ALTSTACK_INIT(GET_VM()->main_altstack, rb_allocate_sigaltstack());
|
2019-10-09 23:13:59 +09:00
|
|
|
force_install_sighandler(SIGSEGV, (sighandler_t)sigsegv, &default_sigsegv_handler);
|
1998-01-16 12:13:05 +00:00
|
|
|
#endif
|
2007-06-28 14:22:30 +00:00
|
|
|
}
|
1999-10-12 04:53:36 +00:00
|
|
|
#ifdef SIGPIPE
|
2015-07-26 05:37:59 +00:00
|
|
|
install_sighandler(SIGPIPE, sig_do_nothing);
|
1999-10-12 04:53:36 +00:00
|
|
|
#endif
|
2015-07-26 02:29:03 +00:00
|
|
|
#ifdef SIGSYS
|
|
|
|
install_sighandler(SIGSYS, sig_do_nothing);
|
|
|
|
#endif
|
2003-11-05 14:00:11 +00:00
|
|
|
|
2023-05-15 23:14:51 +09:00
|
|
|
#ifdef RUBY_SIGCHLD
|
|
|
|
install_sighandler(RUBY_SIGCHLD, sighandler);
|
2003-11-05 14:00:11 +00:00
|
|
|
#endif
|
2014-10-28 18:39:45 +00:00
|
|
|
|
|
|
|
rb_enable_interrupt();
|
1998-01-16 12:13:05 +00:00
|
|
|
}
|