ときおり、デバッグの都合により、SIGSEGV や SIGBUS に対する
signal handler を SIG_DFL にしたいことがあるのですが、Ruby
の trap はそれを許してくれません。
trap で "SIG_DFL" と指定しても、Ruby のデフォルトの、[BUG]
と出てくる signal handler が設定されてしまいます。
そのため、core がまともに作れず、デバッグが厄介な場合があり
ます。
そこで、trap で "SYSTEM_DEFAULT" と指定すると本当に SIG_DFL
になるようにしてみたのですがどうでしょうか。
また、trap の説明に、SIG_DFL で the operating system's
default handler になると書いてあるのは嘘だと思います。
Index: signal.c
===================================================================
--- signal.c (リビジョン 12550)
+++ signal.c (作業コピー)
@@ -634,13 +634,62 @@
VALUE cmd;
};
+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:
+#endif
+ func = sighandler;
+ break;
+#ifdef SIGBUS
+ case SIGBUS:
+ func = sigbus;
+ break;
+#endif
+#ifdef SIGSEGV
+ case SIGSEGV:
+ func = sigsegv;
+ break;
+#endif
+#ifdef SIGPIPE
+ case SIGPIPE:
+ func = sigpipe;
+ break;
+#endif
+ default:
+ func = SIG_DFL;
+ break;
+ }
+
+ return func;
+}
+
static RETSIGTYPE
wrong_trap(int sig)
{
}
static sighandler_t
-trap_handler(VALUE *cmd)
+trap_handler(VALUE *cmd, int sig)
{
sighandler_t func = wrong_trap;
VALUE command;
@@ -654,22 +703,32 @@
SafeStringValue(command); /* taint check */
switch (RSTRING_LEN(command)) {
case 0:
- func = SIG_IGN;
+ goto sig_ign;
break;
+ case 14:
+ if (strncmp(RSTRING_PTR(command), "SYSTEM_DEFAULT", 14) == 0) {
+ func = SIG_DFL;
+ *cmd = 0;
+ }
+ break;
case 7:
if (strncmp(RSTRING_PTR(command), "SIG_IGN", 7) == 0) {
- func = SIG_IGN;
+sig_ign:
+ func = SIG_IGN;
+ *cmd = 0;
}
else if (strncmp(RSTRING_PTR(command), "SIG_DFL", 7) == 0) {
- func = SIG_DFL;
+sig_dfl:
+ func = default_handler(sig);
+ *cmd = 0;
}
else if (strncmp(RSTRING_PTR(command), "DEFAULT", 7) == 0) {
- func = SIG_DFL;
+ goto sig_dfl;
}
break;
case 6:
if (strncmp(RSTRING_PTR(command), "IGNORE", 6) == 0) {
- func = SIG_IGN;
+ goto sig_ign;
}
break;
case 4:
@@ -689,9 +748,6 @@
func = sighandler;
}
}
- if (func == SIG_IGN || func == SIG_DFL) {
- *cmd = 0;
- }
return func;
}
@@ -734,53 +790,6 @@
return sig;
}
-static sighandler_t
-default_handler(sighandler_t func, int sig)
-{
- if (func == SIG_DFL) {
- 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:
-#endif
- func = sighandler;
- break;
-#ifdef SIGBUS
- case SIGBUS:
- func = sigbus;
- break;
-#endif
-#ifdef SIGSEGV
- case SIGSEGV:
- func = sigsegv;
- break;
-#endif
-#ifdef SIGPIPE
- case SIGPIPE:
- func = sigpipe;
- break;
-#endif
- }
- }
-
- return func;
-}
-
static VALUE
trap(struct trap_arg *arg)
{
@@ -851,10 +860,12 @@
* signal name. The command or block specifies code to be run when the
* 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 operating system's default handler
+ * ``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. Otherwise, the given command or block
* will be run.
+ * If the command is ``SYSTEM_DEFAULT'', the operating system's default
+ * handler will be invoked.
* 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.
@@ -885,7 +896,7 @@
}
else if (argc == 2) {
arg.cmd = argv[1];
- arg.func = default_handler(trap_handler(&arg.cmd), arg.sig);
+ arg.func = trap_handler(&arg.cmd, arg.sig);
}
if (OBJ_TAINTED(arg.cmd)) {
--
[田中 哲][たなか あきら][Tanaka Akira]