Rcov & Ruby 1.8.5

Is it my fevered imagination, or has Ruby-1.8.5 clobbered rcov-0.7.0,
causing it to segfault.

Here is a backtrace...
#0 coverage_mark_caller () at rcovrt.c:81
#1 0xb7b19535 in coverage_event_coverage_hook (event=<value optimized out>, node=0xb7bd9450, self=3082662880, mid=23425, klass=3082634620) at rcovrt.c:154
#2 0x0805ded5 in rb_call0 (klass=<value optimized out>, recv=3082662880, id=23425, oid=23425, argc=0, argv=0x0, body=0xb7bd948c, flags=<value optimized out>) at eval.c:5952
#3 0x0805e751 in rb_call (klass=3082634620, recv=3082662880, mid=23425, argc=0, argv=0x0, scope=0) at eval.c:6048
#4 0x0805c010 in rb_eval (self=3082629180, n=<value optimized out>) at eval.c:3443
#5 0x0805d3df in rb_eval (self=3082629180, n=<value optimized out>) at eval.c:3173
#6 0x0805e344 in rb_call0 (klass=<value optimized out>, recv=3082629180, id=11049, oid=11049, argc=0, argv=0x8, body=0xb7be8ae0, flags=<value optimized out>) at eval.c:5954
#7 0x0805e751 in rb_call (klass=3082663220, recv=3082629180, mid=11049, argc=0, argv=0x8, scope=3) at eval.c:6048
#8 0x0806039e in rb_call_super (argc=0, argv=0x8) at eval.c:6216
#9 0x0805af10 in rb_eval (self=3082629180, n=<value optimized out>) at eval.c:3505
#10 0x0805e344 in rb_call0 (klass=<value optimized out>, recv=3082629180, id=11049, oid=11049, argc=0, argv=0x0, body=0xb7be5c78, flags=<value optimized out>) at eval.c:5954
#11 0x0805e751 in rb_call (klass=3082663160, recv=3082629180, mid=11049, argc=0, argv=0x0, scope=0) at eval.c:6048
#12 0x0805c010 in rb_eval (self=3084253680, n=<value optimized out>) at eval.c:3443
#13 0x080692ae in ruby_exec_internal () at eval.c:1604
#14 0x080692e6 in ruby_exec () at eval.c:1624
#15 0x08069311 in ruby_run () at eval.c:1634
#16 0x08052474 in main (argc=Cannot access memory at address 0x2
) at main.c:46

Looking in coverage_mark_caller () at rcovrt.c:81
   for (; frame && (n = frame->node); frame = frame->prev) {
           if (frame->prev && frame->prev->last_func) {
                   if (frame->prev->node == n) continue;
                   coverage_increase_counter_uncached(n->nd_file, nd_line(n) - 1, 1);
           }
           else {
-line 81--> coverage_increase_counter_uncached(n->nd_file, nd_line(n) - 1, 1);
           }
           break;
   }

if I print out n, it's value is (NODE *) 0x2

If I print frame the value is (struct FRAME *) 0x0

p *ruby_frame $8 = {
   self = 3082662880,
   argc = 0,
   last_func = 23425,
   orig_func = 23425,
   last_class = 3082634620,
   prev = 0xbfd285e4,
   tmp = 0x0,
   node = 0xb7be8a2c,
   iter = 2,
   flags = 0,
   uniq = 15318
}

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

...even the weariest river winds somewhere safe to sea.

John Carter wrote:

Is it my fevered imagination, or has Ruby-1.8.5 clobbered rcov-0.7.0,
causing it to segfault.

I may not have exercised everything it can do, but for a contrary
data point I can say that rcov-0.7.0 does run OK on Windows
with ruby installed via OneClickInstaller 185-21 and rcov installed
as a gem. I have run it 'stand-alone' from the command line and
via rake using the Spec::Rake::SpecTask shipped with rSpec.

I guess it might be different on other platforms?

DJ

···

--
Posted via http://www.ruby-forum.com/.

Is it my fevered imagination, or has Ruby-1.8.5 clobbered rcov-0.7.0,
causing it to segfault.

AFAIK it works with ruby 1.8.5 (I just ran it on Pimki's tests to make sure) [1].

Here is a backtrace...

#0 coverage_mark_caller () at rcovrt.c:81

[...]

Looking in coverage_mark_caller () at rcovrt.c:81
  for (; frame && (n = frame->node); frame = frame->prev) {
          if (frame->prev && frame->prev->last_func) {
                  if (frame->prev->node == n) continue;
                  coverage_increase_counter_uncached(n->nd_file, nd_line(n)
                  - 1, 1);
          }
          else {
-line 81--> coverage_increase_counter_uncached(n->nd_file, nd_line(n)
- 1, 1);
          }
          break;
  }

if I print out n, it's value is (NODE *) 0x2

This code was mostly taken from eval.c's backtrace(). It was changed on
Jul 24, but the modification doesn't seem to imply that the above would
segfault under 1.8.5. At any rate, here's the patch to mirror the new
backtrace():

diff -rN -u old-head/ext/rcovrt/rcovrt.c new-head/ext/rcovrt/rcovrt.c
--- old-head/ext/rcovrt/rcovrt.c 2006-09-04 16:46:46.000000000 +0200
+++ new-head/ext/rcovrt/rcovrt.c 2006-09-04 16:46:46.000000000 +0200
@@ -74,7 +74,9 @@
   }
   for (; frame && (n = frame->node); frame = frame->prev) {
           if (frame->prev && frame->prev->last_func) {
- if (frame->prev->node == n) continue;
+ if (frame->prev->node == n) {
+ if (frame->prev->last_func == frame->last_func) continue;
+ }
                   coverage_increase_counter_uncached(n->nd_file, nd_line(n) - 1, 1);
           }
           else {

I wouldn't expect that to prevent the segfault (which I cannot reproduce
anyway), but that's the only patch I can think of right now.

We're looking for either:
* a bug in coverage_mark_caller due to my misunderstanding of backtrace()'s
  code in eval.c
* a genuine bug in Ruby (why would a frame->node == 2)
* something caused by a buggy extension (the usual suspect used to be syck,
  but it's gotten better as of late :wink:

Is there any way to reproduce the segfault?

[1] 1.8.5 breaks rcov in pure-Ruby mode, but I don't think anybody is using
it anyway, since it's over 100 times slower... I'll try to fix that though.

···

On Fri, Sep 01, 2006 at 02:16:58PM +0900, John Carter wrote:

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Yip. That fixed it!

Thanks!

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

"We have more to fear from
  The Bungling of the Incompetent
  Than from the Machinations of the Wicked." (source unknown)

···

On Tue, 5 Sep 2006, Mauricio Fernandez wrote:

On Fri, Sep 01, 2006 at 02:16:58PM +0900, John Carter wrote:

Is it my fevered imagination, or has Ruby-1.8.5 clobbered rcov-0.7.0,
causing it to segfault.

This code was mostly taken from eval.c's backtrace(). It was changed on
Jul 24, but the modification doesn't seem to imply that the above would
segfault under 1.8.5. At any rate, here's the patch to mirror the new
backtrace():

diff -rN -u old-head/ext/rcovrt/rcovrt.c new-head/ext/rcovrt/rcovrt.c

That's good news but I'd have liked to understand why :slight_smile:

I'll apply that patch for the next release; probably compiling it
conditionally. While it looks like it should work with <1.8.5, I'm obviously
missing something because I don't quite see why it fixed the segfault you
reported :slight_smile: (iow. I have yet to find the modification that allowed
frame->node to hold invalid pointers).

···

On Tue, Sep 05, 2006 at 10:53:42AM +0900, John Carter wrote:

On Tue, 5 Sep 2006, Mauricio Fernandez wrote:

>On Fri, Sep 01, 2006 at 02:16:58PM +0900, John Carter wrote:
>>Is it my fevered imagination, or has Ruby-1.8.5 clobbered rcov-0.7.0,
>>causing it to segfault.

>This code was mostly taken from eval.c's backtrace(). It was changed on
>Jul 24, but the modification doesn't seem to imply that the above would
>segfault under 1.8.5. At any rate, here's the patch to mirror the new
>backtrace():
>
>
>diff -rN -u old-head/ext/rcovrt/rcovrt.c new-head/ext/rcovrt/rcovrt.c

Yip. That fixed it!

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

If you can think of some good way to instrument things to find out, I'll
gladly do it.

John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter@tait.co.nz
New Zealand

"We have more to fear from
  The Bungling of the Incompetent
  Than from the Machinations of the Wicked." (source unknown)

···

On Wed, 6 Sep 2006, Mauricio Fernandez wrote:

diff -rN -u old-head/ext/rcovrt/rcovrt.c new-head/ext/rcovrt/rcovrt.c

Yip. That fixed it!

That's good news but I'd have liked to understand why :slight_smile: