Ruby Forum Ruby-core > Sigsegv when running Kernel rubysecs with ruby_1_8 branch

Posted by Vladimir Sizikov (Guest)
on 06.04.2008 01:26
(Received via mailing list)
Hi,

Yet another SIGSEGV on Ubuntu Linux 7.10, when running Kernel
rubyspecs with the latest MRI from 1_8 branch.

Sorry, I couldn't yet minimize the test case, just running the whole
kernel specs like that:

bin/mspec -t /opt/work/ruby18x.git/ruby spec/ruby/1.8/core/kernel/

leads to:
Segmentation fault

While I wasn't able to minimize the test case, I was able to bisect to
the exact revision that started causing the SIGSEV:
rev. r15856: "class.c (clone_method): should copy cref as well.
[ruby-core:15833]"

Thanks,
  --Vladimir
Posted by ts (Guest)
on 06.04.2008 12:09
(Received via mailing list)
Vladimir Sizikov wrote:
> Sorry, I couldn't yet minimize the test case, just running the whole
> kernel specs like that:

 Where can it be loaded ?

> rev. r15856: "class.c (clone_method): should copy cref as well.
> [ruby-core:15833]"

 I find strange this modification

 * don't handle NODE_BMETHOD and NODE_DMETHOD

 * it do the equivalent of a PUSH_CREF()
   when it must change cref in the node

 * give strange value to klass


Guy Decoux
Posted by Vladimir Sizikov (Guest)
on 06.04.2008 12:46
(Received via mailing list)
Hi,

On Sun, Apr 6, 2008 at 12:08 PM, ts <decoux@moulon.inra.fr> wrote:
> Vladimir Sizikov wrote:
>  > Sorry, I couldn't yet minimize the test case, just running the whole
>  > kernel specs like that:
>
>   Where can it be loaded ?

I've written a small quick starting guide here:
http://blog.emptyway.com/2008/04/06/the-rubyspecs-quick-starting-guide/

Thanks,
  --Vladimir
Posted by ts (Guest)
on 06.04.2008 13:09
(Received via mailing list)
Vladimir Sizikov wrote:
> I've written a small quick starting guide here:
> http://blog.emptyway.com/2008/04/06/the-rubyspecs-quick-starting-guide/

 Thanks,

vgs% bin/mspec -t ruby spec/ruby/1.8/core/kernel
ruby 1.8.6 (2008-04-06 patchlevel 5000) [i686-linux]
.......................................................................................................................................................................................................................................................................................................................

Finished in 0.190939 seconds

101 files, 311 examples, 2658 expectations, 0 failures, 0 errors
vgs%


 Please verify it

Guy Decoux




Index: intern.h
===================================================================
--- intern.h  (revision 15910)
+++ intern.h  (working copy)
@@ -184,6 +184,8 @@
 void rb_obj_call_init _((VALUE, int, VALUE*));
 VALUE rb_class_new_instance _((int, VALUE*, VALUE));
 VALUE rb_block_proc _((void));
+VALUE rb_block_dup _((VALUE, VALUE, VALUE));
+VALUE rb_method_dup _((VALUE, VALUE, VALUE));
 VALUE rb_f_lambda _((void));
 VALUE rb_proc_new _((VALUE (*)(ANYARGS/* VALUE yieldarg[, VALUE
procarg] */), VALUE));
 VALUE rb_protect _((VALUE (*)(VALUE), VALUE, int*));
Index: class.c
===================================================================
--- class.c  (revision 15910)
+++ class.c  (working copy)
@@ -51,6 +51,7 @@
 struct clone_method_data {
     st_table *tbl;
     VALUE klass;
+    VALUE cref;
 };

 static int
@@ -59,18 +60,75 @@
     NODE *body;
     struct clone_method_data *data;
 {
-    NODE *fbody = body->nd_body;
+    NODE *node = body->nd_body;
+    if (node && data->cref) {
+  switch(nd_type(node)) {
+  case NODE_SCOPE:
+      if (node->nd_rval) {
+    NODE *tmp = NEW_NODE(nd_type(node->u2.node), data->cref,
+             node->u2.node->u2.node, node->u2.node->u3.node);
+    node = NEW_NODE(nd_type(node), node->u1.node, tmp, node->u3.node);
+      }
+      break;
+
+  case NODE_BMETHOD:
+  {
+      VALUE body = rb_block_dup(node->nd_cval, data->klass, 
data->cref);
+      node = NEW_BMETHOD(body);
+      break;
+  }
+
+  case NODE_DMETHOD:
+  {
+      VALUE body = rb_method_dup(node->nd_cval, data->klass, 
data->cref);
+      node = NEW_DMETHOD(body);
+      break;
+  }

-    if (fbody && nd_type(fbody) == NODE_SCOPE) {
-  VALUE cref = data->klass ?
-      (VALUE)NEW_NODE(NODE_CREF,data->klass,0,fbody->nd_rval) :
-      fbody->nd_rval;
-  fbody = NEW_NODE(NODE_SCOPE, fbody->nd_tbl, cref, fbody->nd_next);
+  }
     }
-    st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(fbody, 
body->nd_noex));
+    st_insert(data->tbl, mid, (st_data_t)NEW_METHOD(node, 
body->nd_noex));
     return ST_CONTINUE;
 }

+static VALUE
+singleton_class_clone_int(obj, cref)
+    VALUE obj, cref;
+{
+    VALUE klass = RBASIC(obj)->klass;
+
+    if (!FL_TEST(klass, FL_SINGLETON))
+  return klass;
+    else {
+  struct clone_method_data data;
+  /* copy singleton(unnamed) class */
+  NEWOBJ(clone, struct RClass);
+  OBJSETUP(clone, 0, RBASIC(klass)->flags);
+
+  if (BUILTIN_TYPE(obj) == T_CLASS) {
+      RBASIC(clone)->klass = (VALUE)clone;
+  }
+  else {
+      RBASIC(clone)->klass = rb_singleton_class_clone(klass);
+  }
+
+  clone->super = RCLASS(klass)->super;
+  clone->iv_tbl = 0;
+  clone->m_tbl = 0;
+  if (RCLASS(klass)->iv_tbl) {
+      clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
+  }
+  clone->m_tbl = st_init_numtable();
+  data.tbl = clone->m_tbl;
+  data.klass = (VALUE)clone;
+  data.cref = cref;
+  st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data);
+  rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
+  FL_SET(clone, FL_SINGLETON);
+  return (VALUE)clone;
+    }
+}
+
 /* :nodoc: */
 VALUE
 rb_mod_init_copy(clone, orig)
@@ -78,8 +136,7 @@
 {
     rb_obj_init_copy(clone, orig);
     if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) {
-  RBASIC(clone)->klass = RBASIC(orig)->klass;
-  RBASIC(clone)->klass = rb_singleton_class_clone(clone);
+  RBASIC(clone)->klass = singleton_class_clone_int(orig, clone);
     }
     RCLASS(clone)->super = RCLASS(orig)->super;
     if (RCLASS(orig)->iv_tbl) {
@@ -94,9 +151,10 @@
     if (RCLASS(orig)->m_tbl) {
   struct clone_method_data data;

-  data.tbl = RCLASS(clone)->m_tbl = st_init_numtable();
-  data.klass = (VALUE)clone;
-
+   RCLASS(clone)->m_tbl = st_init_numtable();
+  data.tbl = RCLASS(clone)->m_tbl;
+  data.klass = clone;
+  data.cref = clone;
   st_foreach(RCLASS(orig)->m_tbl, clone_method, (st_data_t)&data);
     }

@@ -121,48 +179,7 @@
 rb_singleton_class_clone(obj)
     VALUE obj;
 {
-    VALUE klass = RBASIC(obj)->klass;
-
-    if (!FL_TEST(klass, FL_SINGLETON))
-  return klass;
-    else {
-  /* copy singleton(unnamed) class */
-  NEWOBJ(clone, struct RClass);
-  OBJSETUP(clone, 0, RBASIC(klass)->flags);
-
-  if (BUILTIN_TYPE(obj) == T_CLASS) {
-      RBASIC(clone)->klass = (VALUE)clone;
-  }
-  else {
-      RBASIC(clone)->klass = rb_singleton_class_clone(klass);
-  }
-
-  clone->super = RCLASS(klass)->super;
-  clone->iv_tbl = 0;
-  clone->m_tbl = 0;
-  if (RCLASS(klass)->iv_tbl) {
-      clone->iv_tbl = st_copy(RCLASS(klass)->iv_tbl);
-  }
-  {
-      struct clone_method_data data;
-
-      data.tbl = clone->m_tbl = st_init_numtable();
-      switch (TYPE(obj)) {
-        case T_CLASS:
-        case T_MODULE:
-    data.klass = obj;
-    break;
-        default:
-    data.klass = 0;
-    break;
-      }
-
-      st_foreach(RCLASS(klass)->m_tbl, clone_method, (st_data_t)&data);
-  }
-  rb_singleton_class_attached(RBASIC(clone)->klass, (VALUE)clone);
-  FL_SET(clone, FL_SINGLETON);
-  return (VALUE)clone;
-    }
+    return singleton_class_clone_int(obj, 0);
 }

 void
Index: eval.c
===================================================================
--- eval.c  (revision 15910)
+++ eval.c  (working copy)
@@ -8358,6 +8358,19 @@
     return bind;
 }

+VALUE
+rb_block_dup(self, klass, cref)
+    VALUE self, klass, cref;
+{
+    struct BLOCK *block;
+    VALUE obj = proc_dup(self);
+    Data_Get_Struct(obj, struct BLOCK, block);
+    block->klass = klass;
+    block->cref = NEW_NODE(nd_type(block->cref), cref,
block->cref->u2.node,
+         block->cref->u3.node);
+    return obj;
+}
+
 /*
  *  call-seq:
  *     binding -> a_binding
@@ -9204,6 +9217,29 @@
     return clone;
 }

+VALUE
+rb_method_dup(self, klass, cref)
+    VALUE self;
+    VALUE klass;
+    VALUE cref;
+{
+    VALUE clone;
+    struct METHOD *orig, *data;
+
+    Data_Get_Struct(self, struct METHOD, orig);
+    clone = Data_Make_Struct(CLASS_OF(self),struct METHOD, bm_mark,
free, data);
+    *data = *orig;
+    data->rklass = klass;
+    if (data->body->nd_rval) {
+  NODE *tmp = NEW_NODE(nd_type(data->body->u2.node), cref,
+           data->body->u2.node->u2.node,
+           data->body->u2.node->u3.node);
+  data->body = NEW_NODE(nd_type(data->body), data->body->u1.node, tmp,
+            data->body->u3.node);
+    }
+    return clone;
+}
+
 /*
  *  call-seq:
  *     meth.call(args, ...)    => obj
Posted by Vladimir Sizikov (Guest)
on 06.04.2008 13:33
(Received via mailing list)
Hi,

Thanks for quick reply!
Yes, the proposed patch fixed the SIGSEGVs for me.

Thanks,
  --Vladimir
Posted by Akinori MUSHA (Guest)
on 26.04.2008 12:55
(Received via mailing list)
At Sun, 6 Apr 2008 20:08:13 +0900,
ts wrote:
>
> Finished in 0.190939 seconds
>
> 101 files, 311 examples, 2658 expectations, 0 failures, 0 errors
> vgs%
>
>
>  Please verify it

Your patch has been committed to the ruby_1_8 branch with minor
changes.  Thanks!