Rb_gc() and scan stack

I were experimenting with Init_stack, when I discovered a flaw in my mind.

I thought that: local variables on stack would be marked in the
mark-phase and therefore survive the sweep-phase.

But my instance is being destroyed… why ?

Can someone enligthen me ?

expand -t4 rb_gc1.c
#include <ruby.h>

void Dummy_Free(void p) {
printf(“free\n”);
delete [] ((int
)p);
}

VALUE Dummy_Alloc(VALUE self) {
printf(“alloc\n”);
int *p = new int[1];
return Data_Wrap_Struct(self, 0, Dummy_Free, p);
}

VALUE Dummy_Initialize(VALUE self) {
int *p;
printf(“initialize\n”);
Data_Get_Struct(self, int, p);
return self;
}

void Init_dummy() {
VALUE h = rb_define_class(“Dummy”, rb_cObject);
rb_define_alloc_func(h, Dummy_Alloc);
typedef VALUE (*HOOK)(…);
rb_define_method(h, “initialize”, (HOOK)(&Dummy_Initialize), 0);
}

VALUE tst_new_dummy() {
return rb_class_new_instance(0, 0, rb_path2class(“Dummy”));
}

void test() {
VALUE instance = tst_new_dummy();
printf(“1\n”);
rb_p(instance);
// the instance SHOULD survive this step (1_2)
rb_gc();
printf(“2\n”);
rb_p(instance);
// the instance should NOT survive this step (2_3)
instance = Qnil;
rb_gc();
printf(“3\n”);
rb_p(instance);
}

int main(int argc, char **argv) {
ruby_init();
Init_dummy();
test();
return 0;
}

./a.out
alloc
initialize
1
#Dummy:0x8103b38
free
2
ruby: [BUG] Segmentation fault
ruby 1.8.0 (2003-06-23) [i386-freebsd5.0]

Abort (core dumped)

As you can see the ‘free’ is occuring between ‘1’ and ‘2’.

I thought ‘free’ was suppose to happen between ‘2’ and ‘3’ ?
Expecting output should look like this:

alloc
initialize
1
#Dummy:0x8103b38
2
#Dummy:0x8103b38
free
3
ruby: [BUG] Segmentation fault
ruby 1.8.0 (2003-06-23) [i386-freebsd5.0]

Abort (core dumped)

···


Simon Strandgaard

I were experimenting with Init_stack, when I discovered a flaw in my mind.

I thought that: local variables on stack would be marked in the
mark-phase and therefore survive the sweep-phase.

But my instance is being destroyed… why ?

Can someone enligthen me ?

[snip]

As you can see the ‘free’ is occuring between ‘1’ and ‘2’.

I thought ‘free’ was suppose to happen between ‘2’ and ‘3’ ?
Expecting output should look like this:

Init_stack() did solve it :-)… The funny thing is that I were looking
for a short+simple example to illustrate usage of Init_stack().

The modification I made were this:

extern "C" void Init_stack(void *); 
void test() {
    volatile void *tmp;
    Init_stack((void*)&tmp); // comment this line and then step 1_2 will fail.

Im still confused about the rb_gc_stack_start value in my first posting.
Why does it fail in step (1_2), Can someone enligthen me ???

···

On Wed, 02 Jul 2003 01:37:11 +0200, Simon Strandgaard wrote:


Simon Strandgaard

I were experimenting with Init_stack, when I discovered a flaw in my mind.

I thought that: local variables on stack would be marked in the
mark-phase and therefore survive the sweep-phase.

But my instance is being destroyed… why ?

Can someone enligthen me ?
[…]
int main(int argc, char **argv) {
ruby_init();
Init_dummy();
test();
return 0;
}

Could you please check if adding one stack frame in between works?
If it does, it’d mean it’s exactly the same issue described in the links
I provided some time ago, that is, that ruby_init is capturing the
current SP to record the beginning of the stack, but you’re storing
VALUEs in a stack frame above.

Please test adding the following to your code:

void foo()
{
int a, b, c, d, e, f; /* just to take place in the stack /
a = b = c = d = e = f = 1; /
don’t get warnings when -Wall */
test();
}

int main(int argc, char **argv)
{
ruby_init();
Init_dummy();
foo();
return 0;
}

Cannot check now as my primary machine has no connection and the one
I’m writing from has no ruby…

···

On Wed, Jul 02, 2003 at 07:52:17AM +0900, Simon Strandgaard wrote:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Those who don’t understand Linux are doomed to reinvent it, poorly.
– unidentified source

Guy Decoux + others… I know you are reading this… please help :slight_smile:

···

On Wed, 02 Jul 2003 02:14:23 +0200, Simon Strandgaard wrote:

Im still confused about the rb_gc_stack_start value in my first posting.
Why does it fail in step (1_2), Can someone enligthen me ???


Simon Strandgaard

I were experimenting with Init_stack, when I discovered a flaw in my mind.

I thought that: local variables on stack would be marked in the
mark-phase and therefore survive the sweep-phase.

But my instance is being destroyed… why ?

Can someone enligthen me ?
[…]
int main(int argc, char **argv) {
ruby_init();
Init_dummy();
test();
return 0;
}

Could you please check if adding one stack frame in between works?
If it does, it’d mean it’s exactly the same issue described in the links
I provided some time ago, that is, that ruby_init is capturing the
current SP to record the beginning of the stack, but you’re storing
VALUEs in a stack frame above.

Please test adding the following to your code:
[snip]

Cannot check now as my primary machine has no connection and the one
I’m writing from has no ruby…

It doesn’t help… my main now looks like this:

expand -t4 main.c | tail -n12
void foo() {
int a, b, c, d, e, f; /* just to take place in the stack /
a = b = c = d = e = f = 1; /
don’t get warnings when -Wall */
test();
}

int main(int argc, char **argv) {
ruby_init();
Init_dummy();
foo();
return 0;
}

Output is the same:

./a.out
alloc
initialize
1
#Dummy:0x8103b38
free
2
ruby: [BUG] Segmentation fault
ruby 1.8.0 (2003-06-23) [i386-freebsd5.0]

Abort (core dumped)

I tried drawing on some paper, what is happening…
My initial drawing were wrong… Now I understand.
No problemo:

The stack grows againts right.

‘.’ = empty stack range (unkown to GC).
‘R’ = stack range scanned by GC.
left-most-R == rb_gc_stack_end.
right-most-R == rb_gc_stack_begin (set by Init_stack).
‘|’ = current stack pointer.
‘i’ = where the instance is on the stack.

–[ 0 ]-----------------
top/hi […] bottom/lo
>

–[ 1 ]-----------------
entering ruby_init()
top/hi […] bottom/lo
>

–[ 2 ]-----------------
leaving ruby_init()
top/hi [RRRRR…] bottom/lo
>

–[ 3 ]-----------------
entering Init_dummy()
top/hi [RRRRR…] bottom/lo
>

–[ 4 ]-----------------
leaving Init_dummy()
top/hi [RRRRR…] bottom/lo
>

–[ 5 ]-----------------
entering test()
top/hi [RRRRR…] bottom/lo
>

–[ 6 ]-----------------
instance = Dummy.new
The instance is not within the mark-area, therefore it dies!
top/hi [RRRRR…i…] bottom/lo
>

–[ 7 ]-----------------
rb_gc(); /* first time */

The instance is not within the RRRRR range… and
Ruby is therefore unable to mark the instance.
Thus it dies!

top/hi [RRRRR…] bottom/lo
>

If we redo from step6 with Init_stack(begin)… with a
lower begin address, then things will work.

–[ 6a ]-----------------
Init_stack(current_stack_ptr)
top/hi [RRRRRRRR…] bottom/lo
>

–[ 7a ]-----------------
instance = Dummy.new
This time the instance is within the area, and will thus survive
top/hi [RRRRRRRR…] bottom/lo
>

–[ 8a ]-----------------
rb_gc(); /* first time: this time we survie */
top/hi [RRRRRRRR…] bottom/lo
>

–[ 9a ]-----------------
i = nil
top/hi [RRRRRRRR…] bottom/lo
>

–[ 10a ]-----------------
rb_gc(); /* second time: this time we die */
top/hi [RRRRRRRR…] bottom/lo
>

–[ 11a ]-----------------
leaving test();
top/hi [RRRRRRRR…] bottom/lo

···

On Wed, 02 Jul 2003 22:17:41 +0900, Mauricio Fernández wrote:

On Wed, Jul 02, 2003 at 07:52:17AM +0900, Simon Strandgaard wrote:


Simon Strandgaard

Hi,

···

In message “Re: rb_gc() and scan stack” on 03/07/02, “Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com writes:

Im still confused about the rb_gc_stack_start value in my first posting.
Why does it fail in step (1_2), Can someone enligthen me ???

Guy Decoux + others… I know you are reading this… please help :slight_smile:

We can’t say much. As far as I guess stack, position was higher than
the position where Init_stack() was called from ruby_init().

						matz.

Hi,

I tried drawing on some paper, what is happening…
My initial drawing were wrong… Now I understand.
No problemo:

Incorrect.

G == rb_gc_stack_start (set by Init_stack).

–[ 0 ]-----------------
bottom […] top
>

–[ 1 ]-----------------
entering ruby_init()
bottom […G…] top
>

–[ 2 ]-----------------
leaving ruby_init()
bottom [.RRRRRRG…] top
>

–[ 3 ]-----------------
entering Init_dummy()
bottom […RRRRRG…] top
>

–[ 4 ]-----------------
leaving Init_dummy()
bottom [.RRRRRRG…] top
>

–[ 5 ]-----------------
entering test()
bottom […RG…] top
>

–[ 6 ]-----------------
instance = Dummy.new
The instance is not within the mark-area, therefore it dies!
bottom […i.RG…] top
>

If we redo from step6 with Init_stack(begin)… with a
lower begin address, then things will work.

–[ 6a ]-----------------
Init_stack(current_stack_ptr)
bottom […G…] top
>

–[ 7a ]-----------------
instance = Dummy.new
This time the instance is within the area, and will thus survive
bottom […GRiR…] top

···

At Wed, 2 Jul 2003 22:18:15 +0900, Simon Strandgaard wrote:
>


Nobu Nakada

OK… I had a flaw on my initial drawing… I understand now.
See my revisited drawings of the stack, here:
http://ruby-talk.org/74950

I think I am ready to add this as an example of Init_stack, here:

Thanks everyone who looked at it :slight_smile:

···

On Wed, 02 Jul 2003 22:27:28 +0900, Yukihiro Matsumoto wrote:

Hi,

In message “Re: rb_gc() and scan stack” > on 03/07/02, “Simon Strandgaard” 0bz63fz3m1qt3001@sneakemail.com writes:

Im still confused about the rb_gc_stack_start value in my first posting.
Why does it fail in step (1_2), Can someone enligthen me ???

Guy Decoux + others… I know you are reading this… please help :slight_smile:

We can’t say much. As far as I guess stack, position was higher than
the position where Init_stack() was called from ruby_init().

  					matz.


Simon Strandgaard

I have some major/minor problems understanding your diagram.

What confuses me is that ‘G’ is right-most in step 1-6.
And that ‘G’ is left-most in step 7a.
This seems odd to me, Is this really correct behavier ?

I should have mentionen that I am talking about a x86 stack
which grows downward. In my posting the stack therefore had
its high-addeses to the left… and the lower addesses at right.
I see you have swapped ‘bottom’ with ‘top’… this confuses me.
Are you refering to a x86 stack or a motorola stack ?

Thanks Nobu for the otherwise nice diagram :slight_smile:

···

On Wed, 02 Jul 2003 23:43:48 +0900, nobu.nokad wrote:

At Wed, 2 Jul 2003 22:18:15 +0900, > Simon Strandgaard wrote:

I tried drawing on some paper, what is happening…
My initial drawing were wrong… Now I understand.
No problemo:

Incorrect.


Simon Strandgaard

Wrong url… instead
http://ruby-talk.org/74951

Its a nice drawing of what is actually occuring + snapshots
of the stack :slight_smile:

···

On Wed, 02 Jul 2003 16:09:07 +0200, Simon Strandgaard wrote:

OK… I had a flaw on my initial drawing… I understand now.
See my revisited drawings of the stack, here:
http://ruby-talk.org/74950


Simon Strandgaard

Hi,

What confuses me is that ‘G’ is right-most in step 1-6.
And that ‘G’ is left-most in step 7a.
This seems odd to me, Is this really correct behavier ?

It was correct. To be accurate, nothing shouldn’t be marked
in step 2 through 6. But rb_gc_mark_locations(), which marks
stack, swaps its arguments when they are out of order. So
garbages would possibly be marked.

I forgot to remove this now useless code.

I should have mentionen that I am talking about a x86 stack
which grows downward. In my posting the stack therefore had
its high-addeses to the left… and the lower addesses at right.
I see you have swapped ‘bottom’ with ‘top’… this confuses me.
Are you refering to a x86 stack or a motorola stack ?

Both x86 and mc68000 stacks grow downward. IIRC, beginning of
stack is called “bottom”, and the edge where an element is
pushed into and popped from is called “top”.

···

At Thu, 3 Jul 2003 01:00:35 +0900, Simon Strandgaard wrote:


Nobu Nakada

“swaps its arguments”… I oversaw this.
About 5 minuts I just realized this, browsing ‘gc.c’ :slight_smile:

Thanks Nobu.

···

On Thu, 03 Jul 2003 03:48:41 +0900, nobu.nokad wrote:

At Thu, 3 Jul 2003 01:00:35 +0900, Simon Strandgaard wrote:

What confuses me is that ‘G’ is right-most in step 1-6.
And that ‘G’ is left-most in step 7a.
This seems odd to me, Is this really correct behavier ?

It was correct. To be accurate, nothing shouldn’t be marked
in step 2 through 6. But rb_gc_mark_locations(), which marks
stack, swaps its arguments when they are out of order. So
garbages would possibly be marked.


Simon Strandgaard