From: Tanaka Akira Date: 2007-06-15T19:46:07+09:00 Subject: [ruby-dev:30999] trap(sig, "SYSTEM_DEFAULT") ときおり、デバッグの都合により、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]