Infinite recursive call to C function

e$B1sF#$G$9!#e(B

[ruby-core:24794]
e$B$H;w$?$h$&$JLdBj$rC5$7$F$_$^$7$?$,!"$+$J$j$"$j$=$&$G$9!#e(B

$ ./ruby -e ’
class Symbol
include Enumerable
alias to_enum zip
end
:each.zip(:each) { }

Segmentation fault

$ ruby19 -e ’
class Hash
alias default []
end
{}[1]

Segmentation fault

$ ruby19 -e ’
class Object
alias to_open open
public :to_open
end
o = Object.new
eval(“open(#{ ([“o”] * 10000).join(”,") })") # open(o, o, o, o, …)

Segmentation fault

$ ruby19 -e ’
class Time
def to_str
end
end
Time.now <=> “”

Segmentation fault

matz ruby e$B$G$O!"$3$N<j$N%P%0$O$A$^$A$^$HDY$7$F$$$/$H$$$&$3$H$Ge(B
e$B$$$$$N$G$7$g$&$+!#e(B
e$B:G8e$N$OAj8_:F5"$9$k$N$Ge(B rb_funcall_no_recursive
e$B$G$O5_$($=$&$Ke(B
e$B$"$j$^$;$s!#e(B<=>
e$B$G$NAj8_:F5"$OB?J,7k9=$"$j$=$&$G$9$,!"$I$&$7$^e(B
e$B$7$g$&!#e(B

Index: enum.c

— enum.c (revision 25576)
+++ enum.c (working copy)
@@ -1745,7 +1745,11 @@
if (!allary) {
CONST_ID(conv, “to_enum”);
for (i=0; i<argc; i++) {

  •  argv[i] = rb_funcall(argv[i], conv, 1, ID2SYM(id_each));
    
  •  VALUE sym = ID2SYM(id_each);
    
  •  argv[i] = rb_funcall_no_recursive(argv[i], conv, 1, &sym, 
    

enum_zip);

  •  if (argv[i] == Qundef) {
    
  • rb_raise(rb_eRuntimeError, “recursive call to Enumerable#zip”);
  •  }
    
    }
    }
    if (!rb_block_given_p()) {
    Index: io.c
    ===================================================================
    — io.c (revision 25576)
    +++ io.c (working copy)
    @@ -5589,7 +5589,10 @@
    }
    }
    if (redirect) {
  • VALUE io = rb_funcall2(argv[0], to_open, argc-1, argv+1);
  • VALUE io = rb_funcall_no_recursive(argv[0], to_open, argc-1, argv+1,
    rb_f_open);

  • if (io == Qundef) {

  •  rb_raise(rb_eRuntimeError, "recursive call to Kernel#open");
    
  • }

    if (rb_block_given_p()) {
    return rb_ensure(rb_yield, io, io_close, io);
    Index: hash.c
    ===================================================================
    — hash.c (revision 25576)
    +++ hash.c (working copy)
    @@ -494,7 +494,11 @@
    VALUE val;

    if (!RHASH(hash)->ntbl || !st_lookup(RHASH(hash)->ntbl, key, &val))
    {

  • return rb_funcall(hash, id_default, 1, key);
  • VALUE ret = rb_funcall_no_recursive(hash, id_default, 1, &key,
    rb_hash_aref);
  • if (ret == Qundef) {
  •  rb_raise(rb_eRuntimeError, "recursive call to Hash#[]");
    
  • }
  • return ret;
    }
    return val;
    }

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39592] infinite recursive call to C function”
on Fri, 30 Oct 2009 21:46:20 +0900, Yusuke ENDOH [email protected]
writes:

|[ruby-core:24794] e$B$H;w$?$h$&$JLdBj$rC5$7$F$_$^$7$?$,!“$+$J$j$”$j$=$&$G$9!#e(B

|matz ruby e$B$G$O!“$3$N<j$N%P%0$O$A$^$A$^$HDY$7$F$$$/$H$$$&$3$H$Ge(B
|e$B$$$$$N$G$7$g$&$+!#e(B
|e$B:G8e$N$OAj8_:F5”$9$k$N$Ge(B rb_funcall_no_recursive e$B$G$O5_$($=$&$Ke(B
|e$B$“$j$^$;$s!#e(B<=> e$B$G$NAj8_:F5”$OB?J,7k9=$“$j$=$&$G$9$,!”$I$&$7$^e(B
|e$B$7$g$&!#e(B

e$BBP=h$7$?!V$3$l$r;EMM$K$7$J$$!W$H8@$C$?$N$O!“$-$j$,$J$$$3$H$,e(B
e$BMF0W$KM=A[$G$-$?$?$a$G$9!#$N$G!“BP1~$,4JC1$J$b$N$OBP1~$7$^$9e(B
e$B$,!“A4It$A$^$A$^$HBP1~$9$k$9$k$D$b$j$O$”$j$^$;$s!#@dBP$K=*$oe(B
e$B$i$J$$$7!#@5D>!“e(Brb_funcall_no_recursive()e$B$K$D$$$F$b!”$”$/$^$Ge(B
e$B$b<B83$N$D$b$j$G!”$&$^$/$$$+$J$$$h$&$J$ie(Breverte$B$9$k$D$b$j$G$9!#e(B

e$B$G!“$$$:$l$K$7$F$b$3$NL58B:F5”$,e(BSEGVe$B$K$J$k$3$H$NJ}$r@h$KBP=he(B
e$B$9$Y$-$@$H;W$$$^$9!#$J$+$@$5$s$K$h$k$H!"$3$l<+BN$,%P%0$N$h$&e(B
e$B$@$7!#e(B

e$B$J$+$@$G$9!#e(B

At Sat, 31 Oct 2009 00:01:52 +0900,
Yukihiro M. wrote in [ruby-dev:39596]:

e$B$G!"$$$:$l$K$7$F$b$3$NL58B:F5"$,e(BSEGVe$B$K$J$k$3$H$NJ}$r@h$KBP=he(B
e$B$9$Y$-$@$H;W$$$^$9!#$J$+$@$5$s$K$h$k$H!"$3$l<+BN$,%P%0$N$h$&e(B
e$B$@$7!#e(B

r23720e$B$re(Breverte$B$9$l$Pe(BSEGVe$B$7$J$/$J$j$^$9!#e(Brb_longjmp()e$BCf$Ne(B
rb_make_backtrace()e$B$Ge(BGCe$B$,5/$-$F!"BeBX%9%?%C%/$+$iDL>o$N%9%?%C%/e(B
e$B$^$Ge(Bsweepe$B$7$h$&$H$7$FMn$A$F$$$k46$8$G$9!#e(B

e$B$?$H$($Pe(Brb_make_backtrace()e$B$+$ie(Bset_backtrace()e$B$^$Ge(BGCe$B$r6X;_$9$k$3e(B
e$B$H$G$bMn$A$J$/$J$j$^$9$,!"$=$b$=$be(Bmalloce$B$NESCf$G%7%0%J%k$r<u$1$Fe(B
e$B$$$k$3$H$b$"$j$&$k$o$1$G!"L5>r7o$KI|5"2DG=$JNc30$rEj$2$k$N$b4m81e(B
e$B$J5$$,$7$^$9!#e(B

e$B1sF#$G$9!#e(B

2009e$BG/e(B10e$B7ne(B31e$BF|e(B0:01 Yukihiro M.
[email protected]:

e$B$b<B83$N$D$b$j$G!“$&$^$/$$$+$J$$$h$&$J$ie(Breverte$B$9$k$D$b$j$G$9!#e(B
e$BN;2r$7$^$7$?!#e(B
e$B$G$O!”$b$7e(B rb_funcall_no_recursive()
e$B$,Mn$ACe$$$?$iF~$l$^$9!"e(B
e$B$H;W$C$?$i$b$&>C$5$l$F$^$7$?!#3hH/$J3+H/!#e(B

e$B$G!“$$$:$l$K$7$F$b$3$NL58B:F5”$,e(BSEGVe$B$K$J$k$3$H$NJ}$r@h$KBP=he(B
e$B$9$Y$-$@$H;W$$$^$9!#$J$+$@$5$s$K$h$k$H!"$3$l<+BN$,%P%0$N$h$&e(B
e$B$@$7!#e(B

e$B$=$&$$$($Pe(B sigaltstack e$B$r;H$C$F$^$7$?$M!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39599] Re: infinite recursive call to C
function”
on Mon, 2 Nov 2009 10:15:30 +0900, Nobuyoshi N.
[email protected] writes:

|r23720e$B$re(Breverte$B$9$l$Pe(BSEGVe$B$7$J$/$J$j$^$9!#e(Brb_longjmp()e$BCf$Ne(B
|rb_make_backtrace()e$B$Ge(BGCe$B$,5/$-$F!"BeBX%9%?%C%/$+$iDL>o$N%9%?%C%/e(B
|e$B$^$Ge(Bsweepe$B$7$h$&$H$7$FMn$A$F$$$k46$8$G$9!#e(B

scan?

|e$B$?$H$($Pe(Brb_make_backtrace()e$B$+$ie(Bset_backtrace()e$B$^$Ge(BGCe$B$r6X;_$9$k$3e(B
|e$B$H$G$bMn$A$J$/$J$j$^$9$,!“$=$b$=$be(Bmalloce$B$NESCf$G%7%0%J%k$r<u$1$Fe(B
|e$B$$$k$3$H$b$”$j$&$k$o$1$G!"L5>r7o$KI|5"2DG=$JNc30$rEj$2$k$N$b4m81e(B
|e$B$J5$$,$7$^$9!#e(B

e$B$&!<$`!"$H$&$$$&$3$H$O!"e(B

e$BBeBX%9%?%C%/Cf$G$Oe(BRubye$B%3!<%I$r<B9T$7$J$$e(B(r23720e$B$r%j%P!<e(B
e$B%H$9$ke(B)

  • e$BBeBX%9%?%C%/;HMQCf$O%9%?%C%/@hF,%"%I%l%9$b=q$-49$($ke(B

e$B$N$$$:$l$+$,I,MW$H$$$&$3$H$G$9$+!#e(B

e$B$=$l$h$j$b$`$7$me(Brb_longjmp
e$B$G$Ne(Bbacktracee$B$N3d$jEv$F$re(Blazye$B$K$9e(B
e$B$Y$-$J$N$+$J$“!#$G$b!”%P%C%/$H%l!<%9>pJs$r5-O?$9$k>l=j$O$$$:e(B
e$B$l$K$;$hI,MW$J$o$1$@$7e(B…e$B!#e(B

e$B$J$+$@$G$9!#e(B

At Mon, 2 Nov 2009 11:52:04 +0900,
Yukihiro M. wrote in [ruby-dev:39601]:

|e$B$^$Ge(Bsweepe$B$7$h$&$H$7$FMn$A$F$$$k46$8$G$9!#e(B

scan?

e$B$G$7$?!#e(BGCe$B$O>$7$/$J$$$b$N$G!#e(B

e$B$N$$$:$l$+$,I,MW$H$$$&$3$H$G$9$+!#e(B

e$BA0<T$N$[$&$,$$$$$s$8$c$J$$$G$7$g$&$+!#BeBX%9%?%C%/;HMQCf$Ne(BGCe$B$G%9e(B
e$B%?%C%/%*!<%P%U%m!<$7$?$j$H$+9M$($k$H!#e(B

e$B$=$l$h$j$b$`$7$me(Brb_longjmp e$B$G$Ne(Bbacktracee$B$N3d$jEv$F$re(Blazye$B$K$9e(B
e$B$Y$-$J$N$+$J$"!#$G$b!"%P%C%/$H%l!<%9>pJs$r5-O?$9$k>l=j$O$$$:e(B
e$B$l$K$;$hI,MW$J$o$1$@$7e(B…e$B!#e(B

e$B!V%P%C%/%H%l!<%9>pJs$r5-O?$9$k>l=j!W$H$$$&$N$Oe(B?

e$B$H$j$"$($:e(BJUMP_TAGe$B$N$H$-$K%A%’%C%/$5$;$k$h$&$K$7$F$_$^$7$?!#e(B

Index: eval_error.c

— eval_error.c (revision 25629)
+++ eval_error.c (working copy)
@@ -273,2 +273,14 @@ error_handle(int ex)
return status;
}
+
+void
+ruby_threadptr_handle_critical_exception(rb_thread_t *th)
+{

  • VALUE e = th->errinfo, bt;
  • if (!OBJ_FROZEN(e)) return;
  • if (ruby_threadptr_stack_check(th)) return;
  • bt = rb_threadptr_backtrace(th, -1);
  • th->errinfo = e = rb_obj_dup(e);
  • set_backtrace(e, bt);
  • rb_thread_raised_reset(th, RAISED_STACKOVERFLOW|RAISED_NOMEMORY);
    +}
    Index: eval_intern.h
    ===================================================================
    — eval_intern.h (revision 25629)
    +++ eval_intern.h (working copy)
    @@ -131,5 +131,7 @@ NORETURN(void _longjmp(jmp_buf, int));

#define TH_JUMP_TAG(th, st) do { \

  • ruby_longjmp(th->tag->buf,(st)); \
  • if (rb_thread_raised_p(th, RAISED_STACKOVERFLOW|RAISED_NOMEMORY)) \
  • ruby_threadptr_handle_critical_exception(th); \
  • ruby_longjmp(th->tag->buf,(st));
    } while (0)

@@ -192,4 +194,6 @@ int rb_threadptr_reset_raised(rb_thread_
#define rb_thread_raised_p(th, f) (((th)->raised_flag & (f)) != 0)
#define rb_thread_raised_clear(th) ((th)->raised_flag = 0)
+void ruby_threadptr_handle_critical_exception(rb_thread_t *th);
+int ruby_threadptr_stack_check(rb_thread_t *th);

VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
Index: gc.c

— gc.c (revision 25629)
+++ gc.c (working copy)
@@ -1205,9 +1205,8 @@ ruby_stack_length(VALUE **p)
}

-static int
-stack_check(void)
+int
+ruby_threadptr_stack_check(rb_thread_t *th)
{
int ret;

  • rb_thread_t *th = GET_THREAD();
    SET_STACK_END;
    ret = STACK_LENGTH > STACK_LEVEL_MAX - GC_WATER_MARK;
    @@ -1221,4 +1220,10 @@ stack_check(void)
    }

+static inline int
+stack_check(void)
+{

  • return ruby_threadptr_stack_check(GET_THREAD());
    +}

int
ruby_stack_check(void)
Index: signal.c

— signal.c (revision 25629)
+++ signal.c (working copy)
@@ -599,6 +599,4 @@ sigsegv(int sig SIGINFO_ARG)
{
#ifdef USE_SIGALTSTACK

  • int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
  • NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
    rb_thread_t *th = GET_THREAD();
    if (ruby_stack_overflowed_p(th, info->si_addr)) {
    Index: thread.c
    ===================================================================
    — thread.c (revision 25629)
    +++ thread.c (working copy)
    @@ -1347,12 +1347,7 @@ void
    ruby_thread_stack_overflow(rb_thread_t *th)
    {
  • th->raised_flag = 0;
    -#ifdef USE_SIGALTSTACK
  • th->raised_flag = 0;
  • rb_exc_raise(sysstack_error);
    -#else
  • th->raised_flag = RAISED_STACKOVERFLOW;
    th->errinfo = sysstack_error;
  • TH_JUMP_TAG(th, TAG_RAISE);
    -#endif
  • ruby_longjmp(th->tag->buf, TAG_RAISE);
    }

Index: vm_core.h

— vm_core.h (revision 25629)
+++ vm_core.h (working copy)
@@ -616,6 +616,8 @@ void *rb_thread_call_with_gvl(void *(*fu
int ruby_thread_has_gvl_p(void);
VALUE rb_make_backtrace(void);
+VALUE rb_threadptr_backtrace(rb_thread_t *th, int lev);
typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
int rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg);
+int rb_threadptr_backtrace_each(rb_thread_t *th, int lev,
rb_backtrace_iter_func *iter, void *arg);
rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th,
rb_control_frame_t *cfp);
VALUE rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE
method);
@@ -654,4 +656,6 @@ void rb_threadptr_signal_raise(rb_thread
void rb_threadptr_signal_exit(rb_thread_t *th);
void rb_threadptr_execute_interrupts(rb_thread_t *);
+int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
+void ruby_thread_stack_overflow(rb_thread_t *th);

#define RUBY_VM_CHECK_INTS_TH(th) do {
Index: vm_eval.c

— vm_eval.c (revision 25629)
+++ vm_eval.c (working copy)
@@ -192,11 +192,8 @@ rb_call_super(int argc, const VALUE *arg

static inline void
-stack_check(void)
+stack_check(rb_thread_t *th)
{

  • rb_thread_t *th = GET_THREAD();
  • if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) &&
    ruby_stack_check()) {
  • rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
  • rb_exc_raise(sysstack_error);
  • ruby_thread_stack_overflow(th);
    }
    }
    @@ -231,5 +228,5 @@ rb_call0(VALUE recv, ID mid, int argc, c
    return method_missing(recv, mid, argc, argv, call_status);
    }
  • stack_check();
  • stack_check(th);
    return vm_call0(th, recv, mid, argc, argv, me);
    }
    @@ -286,5 +283,5 @@ check_funcall(VALUE recv, ID mid, int ar
    }
    }
  • stack_check();
  • stack_check(th);
    return vm_call0(th, recv, mid, argc, argv, me);
    }
    @@ -434,5 +431,5 @@ raise_method_missing(rb_thread_t *th, in
    }
  • stack_check();
  • stack_check(th);

    id = SYM2ID(argv[0]);
    @@ -1524,4 +1521,16 @@ rb_thread_backtrace(VALUE thval)

int
+rb_threadptr_backtrace_each(rb_thread_t *th, int lev,
rb_backtrace_iter_func *iter, void *arg)
+{

  • return vm_backtrace_each(th, lev, iter, arg);
    +}

+VALUE
+rb_threadptr_backtrace(rb_thread_t *th, int lev)
+{

  • return vm_backtrace(th, lev);
    +}

+int
rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
{

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39602] Re: infinite recursive call to C
function”
on Mon, 2 Nov 2009 15:36:51 +0900, Nobuyoshi N.
[email protected] writes:

|> * e$BBeBX%9%?%C%/Cf$G$Oe(BRubye$B%3!<%I$r<B9T$7$J$$e(B(r23720e$B$r%j%P!<e(B
|> e$B%H$9$ke(B)
|> * e$BBeBX%9%?%C%/;HMQCf$O%9%?%C%/@hF,%"%I%l%9$b=q$-49$($ke(B
|>
|> e$B$N$$$:$l$+$,I,MW$H$$$&$3$H$G$9$+!#e(B
|
|e$BA0<T$N$[$&$,$$$$$s$8$c$J$$$G$7$g$&$+!#BeBX%9%?%C%/;HMQCf$Ne(BGCe$B$G%9e(B
|e$B%?%C%/%*!<%P%U%m!<$7$?$j$H$+9M$($k$H!#e(B

e$B$H$9$k$H!"e(B[ruby-core:23813]e$B$,:FH/$9$k$s$8$c$J$$$+$,?4G[$J$Ne(B
e$B$G$9$,!#e(B

|> e$B$=$l$h$j$b$`$7$me(Brb_longjmp e$B$G$Ne(Bbacktracee$B$N3d$jEv$F$re(Blazye$B$K$9e(B
|> e$B$Y$-$J$N$+$J$“!#$G$b!”%P%C%/$H%l!<%9>pJs$r5-O?$9$k>l=j$O$$$:e(B
|> e$B$l$K$;$hI,MW$J$o$1$@$7e(B…e$B!#e(B
|
|e$B!V%P%C%/%H%l!<%9>pJs$r5-O?$9$k>l=j!W$H$$$&$N$Oe(B?

e$B8=:_$Oe(Bbacktracee$B>pJs$rJ8;zNs$NG[Ns$H$7$Fe(Brb_longjmpe$B$NCf$G@8@.$7e(B
e$B$F$$$^$9$,!“$3$l$O$+$J$i$:$7$bI,MW$H$O8B$j$^$;$s!#$?$H$($P!“e(B
e$BNc30$re(Brecuee$B$G%O%s%I%k$7$?>l9g$K$O!”$3$N%%V%8%'%/%H$O;H$o$l$:e(B
e$B$K=
$o$j$^$9!#$N$G!”!V$I$N%U%!%$%k!W!“!V2?9TL!W!”!V$I$N%a%=%Ce(B
e$B%I!W$N>pJse(B(e$B!_8F$S=P$7%M%9%H?te(B)e$B$@$1$I$3$+$KJ]B8$7$F$$1$l$P!"e(B
e$BL5BL$J%
%V%8%'%/%H3d$jEv$F$,:o$l$k$O$:$J$s$G$9$,!#!V$I$3$KJ]e(B
e$BB8$9$k$+!W$K$D$$$FNI$$%“%$%G%#%”$,$J$$$s$G$9$h$M$(!#e(B

|e$B$H$j$"$($:e(BJUMP_TAGe$B$N$H$-$K%A%'%C%/$5$;$k$h$&$K$7$F$_$^$7$?!#e(B

e$B$3$l$rEv$F$k$H!“e(Br23720e$B$re(Breverte$B$7$J$/$F$b$h$$!”$H$$$&$o$1$G$Oe(B
e$B$J$$$s$G$7$g$&$M!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39605] Re: infinite recursive call to C
function”
on Mon, 2 Nov 2009 17:36:42 +0900, Nobuyoshi N.
[email protected] writes:

|> e$B$K=$o$j$^$9!#$N$G!“!V$I$N%U%!%$%k!W!”!V2?9TL!W!"!V$I$N%a%=%Ce(B
|> e$B%I!W$N>pJse(B(e$B!_8F$S=P$7%M%9%H?te(B)e$B$@$1$I$3$+$KJ]B8$7$F$
$1$l$P!“e(B
|> e$BL5BL$J%*%V%8%'%/%H3d$jEv$F$,:o$l$k$O$:$J$s$G$9$,!#!V$I$3$KJ]e(B
|> e$BB8$9$k$+!W$K$D$$$FNI$$%”%$%G%#%"$,$J$$$s$G$9$h$M$(!#e(B
|
|e$B@lMQ$N%9%?%C%/$K%a%=%C%I$N8F$S=P$7$4$H$K@Q$s$G$$$/$H$+$G$9$+!#e(B

e$B$=$s$J46$8$G$9$M!#e(B

|> e$B$3$l$rEv$F$k$H!“e(Br23720e$B$re(Breverte$B$7$J$/$F$b$h$$!”$H$$$&$o$1$G$Oe(B
|> e$B$J$$$s$G$7$g$&$M!#e(B
|
| if (ruby_threadptr_stack_check(th)) return;
|
|e$B$H!“e(Bruby_threadptr_handle_critical_exception()e$B$G%9%?%C%/$K$”$kDxe(B
|e$BEYM>M5$,$G$-$k$^$GBT$C$F$$$^$9!#C1=c$Ke(Br23720e$B$re(Breverte$B$9$k$@$1$G$b!"e(B
|e$B%P%C%/%H%l!<%9$,=P$J$/$J$k$@$1$Ge(BSEGVe$B$O$7$J$$$h$&$G$9$,!#e(B

e$B$A$g$C$H3NG’$5$;$F$/$@$5$$!#L58B:F5"$Ge(BSEGVe$B$9$k$N$O!“e(B
[ruby-dev:39602]e$B$N%Q%C%A$He(Br23720
e$B$Ne(Breverte$B$G2r7h$9$k$s$G$9$+!)e(B
e$B$G$”$l$P!“e(B[ruby-dev:39602]e$B$N%3%_%C%H$K;?@.$7$^$9!#2r7h$7$J$/e(B
e$B$F$b!”$=$s$J$K0-$$%Q%C%A$G$O$J$5$=$&$G$9$,!#e(B

e$B85!9$N!Ve(Bsizee$B$re(Bcounte$B$Ne(Baliase$B!W$G$OH/@8$7$J$/$J$C$F$7$^$C$?$N$G!"e(B
e$B1sF#$5$s$,e(B[ruby-dev:39592]e$B$G>R2p$7$?e(B

class Symbol
include Enumerable
alias to_enum zip
end
:each.zip(:each) { }

e$B$H$+$,NI$$$N$G$O$J$$$+$H;W$$$^$9!#e(B

e$B$J$+$@$G$9!#e(B

At Mon, 2 Nov 2009 16:00:53 +0900,
Yukihiro M. wrote in [ruby-dev:39603]:

e$B%I!W$N>pJse(B(e$B!_8F$S=P$7%M%9%H?te(B)e$B$@$1$I$3$+$KJ]B8$7$F$$1$l$P!"e(B
e$BL5BL$J%
%V%8%’%/%H3d$jEv$F$,:o$l$k$O$:$J$s$G$9$,!#!V$I$3$KJ]e(B
e$BB8$9$k$+!W$K$D$$$FNI$$%"%$%G%#%"$,$J$$$s$G$9$h$M$(!#e(B

e$B@lMQ$N%9%?%C%/$K%a%=%C%I$N8F$S=P$7$4$H$K@Q$s$G$$$/$H$+$G$9$+!#e(B

|e$B$H$j$"$($:e(BJUMP_TAGe$B$N$H$-$K%A%’%C%/$5$;$k$h$&$K$7$F$_$^$7$?!#e(B

e$B$3$l$rEv$F$k$H!“e(Br23720e$B$re(Breverte$B$7$J$/$F$b$h$$!”$H$$$&$o$1$G$Oe(B
e$B$J$$$s$G$7$g$&$M!#e(B

if (ruby_threadptr_stack_check(th)) return;

e$B$H!“e(Bruby_threadptr_handle_critical_exception()e$B$G%9%?%C%/$K$”$kDxe(B
e$BEYM>M5$,$G$-$k$^$GBT$C$F$$$^$9!#C1=c$Ke(Br23720e$B$re(Breverte$B$9$k$@$1$G$b!"e(B
e$B%P%C%/%H%l!<%9$,=P$J$/$J$k$@$1$Ge(BSEGVe$B$O$7$J$$$h$&$G$9$,!#e(B

e$B$J$+$@$G$9!#e(B

At Mon, 2 Nov 2009 18:27:59 +0900,
Yukihiro M. wrote in [ruby-dev:39608]:

e$B$A$g$C$H3NG’$5$;$F$/$@$5$$!#L58B:F5"$Ge(BSEGVe$B$9$k$N$O!“e(B
[ruby-dev:39602]e$B$N%Q%C%A$He(Br23720 e$B$Ne(Breverte$B$G2r7h$9$k$s$G$9$+!)e(B
e$B$G$”$l$P!“e(B[ruby-dev:39602]e$B$N%3%_%C%H$K;?@.$7$^$9!#2r7h$7$J$/e(B
e$B$F$b!”$=$s$J$K0-$$%Q%C%A$G$O$J$5$=$&$G$9$,!#e(B

[ruby-dev:39602]e$B$N%Q%C%A$Oe(Br23720e$B$Ne(Breverte$B$r4^$s$G$$$^$9!#e(B

e$B85!9$N!Ve(Bsizee$B$re(Bcounte$B$Ne(Baliase$B!W$G$OH/@8$7$J$/$J$C$F$7$^$C$?$N$G!"e(B
e$B1sF#$5$s$,e(B[ruby-dev:39592]e$B$G>R2p$7$?e(B

class Symbol
include Enumerable
alias to_enum zip
end
:each.zip(:each) { }

e$B$H$+$,NI$$$N$G$O$J$$$+$H;W$$$^$9!#e(B

e$B$3$NNc$G$Oe(BSEGVe$B$O$7$^$;$s$,!"%P%C%/%H%l!<%9$b=P$^$;$s$G$7$?!#e(B
[ruby-dev:39593]e$B$NNc$G$O=P$k$N$G$9$,!#$H$$$&$3$H$G>/!92~A1!#e(B

Index: eval_error.c

— eval_error.c (revision 25629)
+++ eval_error.c (working copy)
@@ -273,2 +273,14 @@ error_handle(int ex)
return status;
}
+
+void
+ruby_threadptr_handle_critical_exception(rb_thread_t *th)
+{

  • VALUE e = th->errinfo, bt;
  • if (!OBJ_FROZEN(e)) return;
  • if (ruby_threadptr_stack_check(th)) return;
  • bt = rb_threadptr_backtrace(th, -1);
  • th->errinfo = e = rb_obj_dup(e);
  • set_backtrace(e, bt);
  • rb_thread_raised_reset(th, RAISED_STACKOVERFLOW|RAISED_NOMEMORY);
    +}
    Index: eval_intern.h
    ===================================================================
    — eval_intern.h (revision 25629)
    +++ eval_intern.h (working copy)
    @@ -130,5 +130,10 @@ NORETURN(void _longjmp(jmp_buf, int));
    TH_EXEC_TAG()

+#define HANDLE_CRITICAL_EXCEPTION(th) \

  • (rb_thread_raised_p(th, RAISED_STACKOVERFLOW|RAISED_NOMEMORY) ? \
  • ruby_threadptr_handle_critical_exception(th) : (void)0)
    

#define TH_JUMP_TAG(th, st) do { \

  • HANDLE_CRITICAL_EXCEPTION(th);
    ruby_longjmp(th->tag->buf,(st));
    } while (0)
    @@ -192,4 +197,6 @@ int rb_threadptr_reset_raised(rb_thread_
    #define rb_thread_raised_p(th, f) (((th)->raised_flag & (f)) != 0)
    #define rb_thread_raised_clear(th) ((th)->raised_flag = 0)
    +void ruby_threadptr_handle_critical_exception(rb_thread_t *th);
    +int ruby_threadptr_stack_check(rb_thread_t *th);

VALUE rb_f_eval(int argc, VALUE *argv, VALUE self);
Index: gc.c

— gc.c (revision 25629)
+++ gc.c (working copy)
@@ -1205,9 +1205,8 @@ ruby_stack_length(VALUE **p)
}

-static int
-stack_check(void)
+int
+ruby_threadptr_stack_check(rb_thread_t *th)
{
int ret;

  • rb_thread_t *th = GET_THREAD();
    SET_STACK_END;
    ret = STACK_LENGTH > STACK_LEVEL_MAX - GC_WATER_MARK;
    @@ -1221,4 +1220,10 @@ stack_check(void)
    }

+static inline int
+stack_check(void)
+{

  • return ruby_threadptr_stack_check(GET_THREAD());
    +}

int
ruby_stack_check(void)
Index: signal.c

— signal.c (revision 25629)
+++ signal.c (working copy)
@@ -599,6 +599,4 @@ sigsegv(int sig SIGINFO_ARG)
{
#ifdef USE_SIGALTSTACK

  • int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
  • NORETURN(void ruby_thread_stack_overflow(rb_thread_t *th));
    rb_thread_t *th = GET_THREAD();
    if (ruby_stack_overflowed_p(th, info->si_addr)) {
    Index: thread.c
    ===================================================================
    — thread.c (revision 25629)
    +++ thread.c (working copy)
    @@ -1347,12 +1347,7 @@ void
    ruby_thread_stack_overflow(rb_thread_t *th)
    {
  • th->raised_flag = 0;
    -#ifdef USE_SIGALTSTACK
  • th->raised_flag = 0;
  • rb_exc_raise(sysstack_error);
    -#else
  • th->raised_flag = RAISED_STACKOVERFLOW;
    th->errinfo = sysstack_error;
  • TH_JUMP_TAG(th, TAG_RAISE);
    -#endif
  • ruby_longjmp(th->tag->buf, TAG_RAISE);
    }

Index: vm.c

— vm.c (revision 25629)
+++ vm.c (working copy)
@@ -1132,4 +1132,5 @@ vm_exec(rb_thread_t *th)
VALUE type;

  • HANDLE_CRITICAL_EXCEPTION(th);
    err = th->errinfo;

Index: vm_core.h

— vm_core.h (revision 25629)
+++ vm_core.h (working copy)
@@ -616,6 +616,8 @@ void *rb_thread_call_with_gvl(void *(*fu
int ruby_thread_has_gvl_p(void);
VALUE rb_make_backtrace(void);
+VALUE rb_threadptr_backtrace(rb_thread_t *th, int lev);
typedef int rb_backtrace_iter_func(void *, VALUE, int, VALUE);
int rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg);
+int rb_threadptr_backtrace_each(rb_thread_t *th, int lev,
rb_backtrace_iter_func *iter, void *arg);
rb_control_frame_t *rb_vm_get_ruby_level_next_cfp(rb_thread_t *th,
rb_control_frame_t *cfp);
VALUE rb_name_err_mesg_new(VALUE obj, VALUE mesg, VALUE recv, VALUE
method);
@@ -654,4 +656,6 @@ void rb_threadptr_signal_raise(rb_thread
void rb_threadptr_signal_exit(rb_thread_t *th);
void rb_threadptr_execute_interrupts(rb_thread_t *);
+int ruby_stack_overflowed_p(const rb_thread_t *, const void *);
+void ruby_thread_stack_overflow(rb_thread_t *th);

#define RUBY_VM_CHECK_INTS_TH(th) do {
Index: vm_eval.c

— vm_eval.c (revision 25629)
+++ vm_eval.c (working copy)
@@ -192,11 +192,8 @@ rb_call_super(int argc, const VALUE *arg

static inline void
-stack_check(void)
+stack_check(rb_thread_t *th)
{

  • rb_thread_t *th = GET_THREAD();
  • if (!rb_thread_raised_p(th, RAISED_STACKOVERFLOW) &&
    ruby_stack_check()) {
  • rb_thread_raised_set(th, RAISED_STACKOVERFLOW);
  • rb_exc_raise(sysstack_error);
  • ruby_thread_stack_overflow(th);
    }
    }
    @@ -231,5 +228,5 @@ rb_call0(VALUE recv, ID mid, int argc, c
    return method_missing(recv, mid, argc, argv, call_status);
    }
  • stack_check();
  • stack_check(th);
    return vm_call0(th, recv, mid, argc, argv, me);
    }
    @@ -286,5 +283,5 @@ check_funcall(VALUE recv, ID mid, int ar
    }
    }
  • stack_check();
  • stack_check(th);
    return vm_call0(th, recv, mid, argc, argv, me);
    }
    @@ -434,5 +431,5 @@ raise_method_missing(rb_thread_t *th, in
    }
  • stack_check();
  • stack_check(th);

    id = SYM2ID(argv[0]);
    @@ -1524,4 +1521,16 @@ rb_thread_backtrace(VALUE thval)

int
+rb_threadptr_backtrace_each(rb_thread_t *th, int lev,
rb_backtrace_iter_func *iter, void *arg)
+{

  • return vm_backtrace_each(th, lev, iter, arg);
    +}

+VALUE
+rb_threadptr_backtrace(rb_thread_t *th, int lev)
+{

  • return vm_backtrace(th, lev);
    +}

+int
rb_backtrace_each(rb_backtrace_iter_func *iter, void *arg)
{

e$B$J$+$@$G$9!#e(B

At Tue, 3 Nov 2009 00:05:09 +0900,
Yukihiro M. wrote in [ruby-dev:39610]:

e$B$3$N%Q%C%A$rEv$F$F$b!";d$N$H$3$m$G$Oe(BSEGVe$B$7$^$7$?!#$J$K$,0c$&e(B
e$B$N$+$J!#e(Bvalgrinde$B$G<B9T$7$?$H$3$m!“e(Bvm_push_framee$B$,$”$i$+$8$a3de(B
e$B$jEv$F$?%9%?%C%/NN0h$r1[$($?$H$3$m$^$G%U%l!<%`$re(Bpushe$B$7$F$$$ke(B
e$B$h$&$G$9!#e(B

vm_push_framee$B$H$$$&$3$H$O!"%^%7%s%9%?%C%/$8$c$J$/$Fe(BVMe$B%9%?%C%/$Ge(B
e$B$9$+e(B?

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39613] Re: infinite recursive call to C
function”
on Tue, 3 Nov 2009 02:18:25 +0900, Nobuyoshi N.
[email protected] writes:

|At Tue, 3 Nov 2009 00:05:09 +0900,
|Yukihiro M. wrote in [ruby-dev:39610]:
|> e$B$3$N%Q%C%A$rEv$F$F$b!“;d$N$H$3$m$G$Oe(BSEGVe$B$7$^$7$?!#$J$K$,0c$&e(B
|> e$B$N$+$J!#e(Bvalgrinde$B$G<B9T$7$?$H$3$m!“e(Bvm_push_framee$B$,$”$i$+$8$a3de(B
|> e$B$jEv$F$?%9%?%C%/NN0h$r1[$($?$H$3$m$^$G%U%l!<%`$re(Bpushe$B$7$F$$$ke(B
|> e$B$h$&$G$9!#e(B
|
|vm_push_framee$B$H$$$&$3$H$O!”%^%7%s%9%?%C%/$8$c$J$/$Fe(BVMe$B%9%?%C%/$Ge(B
|e$B$9$+e(B?

e$B$=$&$G$9!#e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39609] Re: infinite recursive call to C
function”
on Mon, 2 Nov 2009 23:27:44 +0900, Nobuyoshi N.
[email protected] writes:

|[ruby-dev:39602]e$B$N%Q%C%A$Oe(Br23720e$B$Ne(Breverte$B$r4^$s$G$$$^$9!#e(B

|> class Symbol
|> include Enumerable
|> alias to_enum zip
|> end
|> :each.zip(:each) { }
|>
|> e$B$H$+$,NI$$$N$G$O$J$$$+$H;W$$$^$9!#e(B
|
|e$B$3$NNc$G$Oe(BSEGVe$B$O$7$^$;$s$,!"%P%C%/%H%l!<%9$b=P$^$;$s$G$7$?!#e(B
|[ruby-dev:39593]e$B$NNc$G$O=P$k$N$G$9$,!#$H$$$&$3$H$G>/!92~A1!#e(B

e$B$3$N%Q%C%A$rEv$F$F$b!";d$N$H$3$m$G$Oe(BSEGVe$B$7$^$7$?!#$J$K$,0c$&e(B
e$B$N$+$J!#e(Bvalgrinde$B$G<B9T$7$?$H$3$m!“e(Bvm_push_framee$B$,$”$i$+$8$a3de(B
e$B$jEv$F$?%9%?%C%/NN0h$r1[$($?$H$3$m$^$G%U%l!<%`$re(Bpushe$B$7$F$$$ke(B
e$B$h$&$G$9!#e(B

e$B$G!“e(BCHECK_STACK_OVERFLOW()e$B$r$”$A$3$ADI2C$7$F$_$^$7$?$,!“8=>]e(B
e$B$OJQ$o$i$J$$$h$&$G$9!#$3$NJU!”$h$/$o$+$i$J$$!#e(B

e$B!!$5$5$@$G$9!%e(B

Yukihiro M. wrote::

|vm_push_framee$B$H$$$&$3$H$O!"%^%7%s%9%?%C%/$8$c$J$/$Fe(BVMe$B%9%?%C%/$Ge(B
|e$B$9$+e(B?

e$B$=$&$G$9!#e(B

e$B!!$[$\M>CL$G$9!%e(B

e$B!!e(BVM
e$B$N%9%?%C%/NN0h%A%’%C%/$O!$?t$r8:$i$9$?$a$K?’!94hD%$C$F$k$s$G!$%%9e(B
e$B$,$"$k$+$b$7$l$J$$$G$9$M$’!%$G$b!$e(BC
e$B%^%7%s%9%?%C%/$N%*!<%P!<%U%m!<$H0c$Ce(B
e$B$F!$%
%9$,$J$1$l$P3N<B$Ke(B trap
e$B=PMh$k$+$i!$$3$N85!9$NLdBj$G$"$k!Ve(BC e$B$G$N:Fe(B
e$B5"$,e(B
SEGVe$B!W$rH4K\E*$K!J0?"@-$r9M$($F!K2r7h$9$k$?$a$K$O!$=y!9$Ke(B Ruby
e$B$Ge(B
e$B=q$-49$($F$$$/I,MW$,$"$k$s$G$9$+$M$’!%e(B

e$B!!$A$J$_$K!$e(BVM e$B%9%?%C%/%!<%P!<%U%m!<$7$?$i!$e(BVM
e$B%9%?%C%/$r?-D%$9$k!$$C$Fe(B
e$B%O%C%/$r$d$j$?$$$s$G$9$,!$;~4V$,L5$$!%C/$+$d$j$^$;$s$+$M!%MhG/!$$&$A$K?7e(B
e$BF~@8$,F~$C$F$-$?$i!$N}=,$G$d$C$F$b$i$
$&$H$O;W$&$s$G$9$,!$e(B1.9.3
e$B$"$?$j$Ke(B
e$BF~$k$+$J$!!%$3$l$,F~$k$H!$$$$m$$$m$H8zN(E*$K$J$k$s$G$9$,!%$D$$$G$K%9%?%Ce(B
e$B%/e(BGCe$B$H$+$b=PMh$k$J!J$3$l$O!$e(Btail call
optimizatione$B$NOC$@$1$I!%$=$&$$$(e(B
e$B$P!$$=$N5DO@$be(Bpendinge$B$@$J$!!K!%e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39616] Re: infinite recursive call to C
function”
on Tue, 3 Nov 2009 09:53:40 +0900, SASADA Koichi [email protected]
writes:

|e$B!!$A$J$_$K!$e(BVM e$B%9%?%C%/%*!<%P!<%U%m!<$7$?$i!$e(BVM e$B%9%?%C%/$r?-D%$9$k!$$C$Fe(B
|e$B%O%C%/$r$d$j$?$$$s$G$9$,!$;~4V$,L5$$!%C/$+$d$j$^$;$s$+$M!%e(B

cfpe$B$H$+%“%I%l%9$,D>@\F~$C$F$$$?$h$&$J5$$,$9$k$s$G!”%U%l!<%`e(B
e$B$r$?$I$C$F%“%I%l%9=q$-49$($kI,MW$,$”$k$s$G$9$+$M!#e(B

e$B!!$5$5$@$G$9!%e(B

Yukihiro M. wrote::

|e$B!!$A$J$_$K!$e(BVM e$B%9%?%C%/%*!<%P!<%U%m!<$7$?$i!$e(BVM e$B%9%?%C%/$r?-D%$9$k!$$C$Fe(B
|e$B%O%C%/$r$d$j$?$$$s$G$9$,!$;~4V$,L5$$!%C/$+$d$j$^$;$s$+$M!%e(B

cfpe$B$H$+%"%I%l%9$,D>@\F~$C$F$$$?$h$&$J5$$,$9$k$s$G!"%U%l!<%`e(B
e$B$r$?$I$C$F%"%I%l%9=q$-49$($kI,MW$,$"$k$s$G$9$+$M!#e(B

e$B!!e(Bcfp
e$B$rO.$k$N$O0l2U=j!Je(Brb_thread_te$B$@$1!K$J$s$G0l=V$G$9$1$I!$e(Blfp,
dfp e$B$re(B
e$BO.$k$N$,BgJQ$=$&$G$9!%5U$K8@$&$H!$$=$l$@$1$H$$$&5$$b$7$^$9!%A4Ite(B
heap e$B$Ke(B
e$BDI$$=P$7$F$7$^$&$C$F$N$b<j$G$9$,!%e(B

e$B!!$"!$%m!<%+%kJQ?t$Ke(B cfp
e$BJ]B8$7$F$k4X?t$,$$$k$N$G!$$=$l$OLdBj$@!%$I$&$7e(B
e$B$?$b$s$+$J!%e(Bcfp e$B$Oe(B index
e$B$K$7$J$$$HBLL$+!)!!$=$N%*!<%P%X%C%I$r4^$a$F%Ze(B
e$B%$$9$k$@$m$&$+!%e(B

e$B$"$H!$L58B:F5"%P%0$,8!CN=PMh$J$/$J$k$N$OLdBj$J$N$G!$e(B

e$BogCM$r$I$3$K$9$k$+!$$H$+!%e(B

e$B$^$D$b$He(B e$B$f$-$R$m$G$9e(B

In message “Re: [ruby-dev:39615] Re: infinite recursive call to C
function”
on Tue, 3 Nov 2009 09:32:45 +0900, Yukihiro M.
[email protected] writes:

||vm_push_framee$B$H$$$&$3$H$O!"%^%7%s%9%?%C%/$8$c$J$/$Fe(BVMe$B%9%?%C%/$Ge(B
||e$B$9$+e(B?
|
|e$B$=$&$G$9!#e(B

e$BF1$8e(BLinuxe$B$N$O$:$J$N$K!"?6$kIq$$$,0c$&$N$O$*$+$7$$$J$H;W$C$Fe(B
e$B$$$?$N$G$9$,!"CfED$5$s$N$H$3$m$G$O%^%7%s%9%?%C%/$N%j%%C%H$,e(B
e$B@h$KMh$F!";d$N$H$3$m$G$Oe(BVMe$B%9%?%C%/%j%
%C%H$,@h$KMh$F$$$k$H$$e(B
e$B$&$3$H$N$h$&$G$9$M!#e(Blimite$B$H$+@_Dj$7$^$9$+!)e(B

e$B$3$A$i$G$Oe(BVMe$B%9%?%C%/$N%A%'%C%/$r2C$($kJ}8~$G:n6H$7$h$&$H;W$$e(B
e$B$^$9!#%^%7%s%9%?%C%/$NJ}$O$*$^$+$;$7$^$9!#e(B