From: nobu.nakada@... Date: 1999-10-17T13:48:50+09:00 Subject: [ruby-dev:8045] signal exception semantics なかだです。 先週から外部と隔離(^^;)されたような状態になってしまって、週末し かメールを読むことができなくなってしまいました。 んで、忘れないうちに先週ちょっと書いてた signal に関する思い付 きを実験したのを書いておきます。(って備忘録じゃないんだから) signal のブロックに限らず、例外に処理されたことを通知してやるっ ていうのはやっぱり不自然でしょうか。 diff --recursive --unified=2 dist/error.c build/error.c --- dist/error.c Sat Oct 16 23:10:10 1999 +++ build/error.c Sun Oct 17 00:14:53 1999 @@ -384,4 +384,11 @@ } +static VALUE +exc_rescued(exc) + VALUE exc; +{ + return Qnil; +} + #ifdef __BEOS__ typedef struct { @@ -504,4 +511,12 @@ static void init_syserr _((void)); +static VALUE +signal_rescued(self) + VALUE self; +{ + rb_signal_unblock(STR2CSTR(rb_iv_get(self, "mesg"))); + return exc_rescued(self); +} + void Init_Exception() @@ -517,4 +532,5 @@ rb_define_method(rb_eException, "backtrace", exc_backtrace, 0); rb_define_method(rb_eException, "set_backtrace", exc_set_backtrace, 1); + rb_define_private_method(rb_eException, "rescued", exc_rescued, 0); rb_eSystemExit = rb_define_class("SystemExit", rb_eException); @@ -522,4 +538,5 @@ rb_eInterrupt = rb_define_class("Interrupt", rb_eException); rb_eSignal = rb_define_class("SignalException", rb_eException); + rb_define_private_method(rb_eSignal, "rescued", signal_rescued, 0); rb_eStandardError = rb_define_class("StandardError", rb_eException); diff --recursive --unified=2 dist/eval.c build/eval.c --- dist/eval.c Sat Oct 16 23:10:10 1999 +++ build/eval.c Sun Oct 17 00:14:54 1999 @@ -2042,9 +2042,14 @@ case NODE_RESCUE: - retry_entry: { volatile VALUE e_info = ruby_errinfo; + retry_entry: PUSH_TAG(PROT_NONE); + if (e_info != ruby_errinfo) { /* retrying */ + if (!NIL_P(ruby_errinfo)) + rb_funcall2(ruby_errinfo, rb_intern("rescued"), 0, 0); + ruby_errinfo = e_info; + } if ((state = EXEC_TAG()) == 0) { result = rb_eval(self, node->nd_head); @@ -2056,4 +2061,6 @@ while (resq) { if (handle_rescue(self, resq)) { + volatile VALUE exc = ruby_errinfo; + state = 0; PUSH_TAG(PROT_NONE); @@ -2068,4 +2075,8 @@ state = 0; goto retry_entry; + } + if (exc != ruby_errinfo) { + /* rescued successfully or new exception raised */ + rb_funcall2(exc, rb_intern("rescued"), 0, 0); } break; diff --recursive --unified=2 dist/signal.c build/signal.c --- dist/signal.c Sat Oct 16 23:10:12 1999 +++ build/signal.c Sun Oct 17 00:14:54 1999 @@ -265,4 +265,10 @@ } +# ifdef HAVE_SIGPROCMASK +static sigset_t trap_last_mask; +# else +static int trap_last_mask; +# endif + static VALUE trap_list[NSIG]; static int trap_pending_list[NSIG]; @@ -346,4 +352,11 @@ int sig; { +#ifdef HAVE_SIGPROCMASK + sigaddset(&trap_last_mask, sig); + sigprocmask(SIG_SETMASK, &trap_last_mask, NULL); +#else + trap_last_mask |= sigmask(sig); + sigsetmask(trap_last_mask); +#endif if (sig >= NSIG) { rb_bug("trap_handler: Bad signal %d", sig); @@ -365,4 +378,24 @@ } +void +rb_signal_unblock(signm) + const char* signm; +{ + int signo; + + if (strncmp("SIG", signm, 3) == 0) + signm += 3; + if (!(signo = signm2signo(signm))) + return; + +#ifdef HAVE_SIGPROCMASK + sigdelset(&trap_last_mask, signo); + sigprocmask(SIG_SETMASK, &trap_last_mask, NULL); +#else + trap_last_mask &= ~sigmask(signo); + sigsetmask(trap_last_mask); +#endif +} + #ifdef SIGBUS static RETSIGTYPE @@ -419,10 +452,4 @@ VALUE sig, cmd; }; - -# ifdef HAVE_SIGPROCMASK -static sigset_t trap_last_mask; -# else -static int trap_last_mask; -# endif static RETSIGTYPE -- そうだ 強気に ちょっと インチキに☆彡 中田 "Bugるくらいがちょうどいいかも;-)" 伸悦