From: victor Date: 2001-06-16T03:20:52+09:00 Subject: [ruby-talk:16503] walking the ruby_frame list Hi, I have a question about the frame list. I am working on implementing a capability security module in Ruby, and I find that in order to to this in a way that is not activly painful to program I need to be able to walk the frame list to snag a reference to the object that invoked the method I use to test for capabilities. Here are diffs for anyone interested: diff -ur ruby-1.6.4/eval.c ruby-1.6.4.hacked/eval.c --- ruby-1.6.4/eval.c Tue May 29 03:59:36 2001 +++ ruby-1.6.4.hacked/eval.c Thu Jun 14 22:42:32 2001 @@ -1510,10 +1510,11 @@ rb_raise(rb_eSecurityError, "Insecure: can't undef"); } rb_frozen_class_p(klass); - if (id == __id__ || id == __send__) { +/* if (id == __id__ || id == __send__) { rb_warn("undefining `%s' may cause serious problem", rb_id2name(id)); - } + } +*/ body = search_method(ruby_class, id, &origin); if (!body || !body->nd_body) { char *s0 = " class"; @@ -3335,6 +3336,28 @@ } static VALUE +rb_f_last_caller(self, testor) +VALUE self, testor; +{ + struct FRAME *foo; + foo = ruby_frame; + /* first, we have to get to the frame. It might be a couple of frames + * up, depending on exceptions and such. */ + while (foo != top_frame && foo->self == self){ + foo = foo->prev; + } + /* now that we are at the right frame, get past it. */ + while (foo != top_frame && foo->self == testor) { + foo = foo->prev; + } + /* if we have a previous frame at all, we are at it now. */ + if (foo == top_frame) + return Qnil; + else return foo->self; + +} + +static VALUE rb_f_abort() { rb_secure(4); @@ -4388,6 +4411,7 @@ } else if (nd_type(body) == NODE_BLOCK) { node = body->nd_head; + body = body->nd_next; } if (node) { @@ -5896,6 +5920,7 @@ rb_define_global_function("loop", rb_f_loop, 0); rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1); + rb_define_method(rb_mKernel, "last_caller", rb_f_last_caller, 1); rb_define_global_function("raise", rb_f_raise, -1); rb_define_global_function("fail", rb_f_raise, -1); As you can see, I am just walking back up the frame list, stopping when I get to one before what I am looking for or at top_frame. The question is, however, whether this method will work correctly when threads are introduced into the picture, or of I need to check for which frame is in what thread as I go (which would be tricky, as I can't determine if threads have their own frame list or if they all share the same frame list). Comments?