From: Suraj Kurapati Date: 2009-11-05T16:27:17+09:00 Subject: [ruby-core:26550] [Feature #2294] [PATCH] ruby_bind_stack() to embed Ruby in coroutine Issue #2294 has been updated by Suraj Kurapati. Hi, According to Matz's suggestion in [ruby-core:25139], I wrote a detailed explanation of the problem this patch solves. I hope this explanation is helpful. Please do not hesitate to ask for clarifications or to correct any misunderstandings. Thanks for your thoughtful consideration. == Introduction The patch adds a ruby_bind_stack() function to the Ruby C API. This function allows the person who is embedding Ruby to tell the Ruby GC about the stack boundaries of the embedded environment: void ruby_bind_stack(VALUE *lower_bound, VALUE *upper_bound); In order to understand why this function is important, please consider the following two modes of operation: normal & embedded. == Normal operation: Ruby runs in a C program's main() Initially, Ruby assumes that the stack of Ruby's main thread exists in a high memory address range, like this: (high memory address) 0xc1bff1f0 Ruby's stack upper boundary 0xbffff1f0 Ruby's stack lower boundary (low memory address) As Ruby runs, the lower boundary is adjusted (by the SET_STACK_END macro) to reflect the machine stack pointer: (high memory address) 0xc1bff1f0 Ruby's stack upper boundary (not changed) 0xc0ff1e80 Ruby's stack lower boundary (after update by SET_STACK_END) (low memory address) == Embedded operation: Ruby runs inside a C coroutine Initially, Ruby assumes that the stack of Ruby's main thread exists in a high memory address range, like this: (high memory address) 0xc1bff1f0 Ruby's stack upper boundary 0xbffff1f0 Ruby's stack lower boundary (low memory address) However, the stack of the C coroutine (which runs Ruby) exists at a low memory address range, because it is statically allocated: (high memory address) 0xc1bff1f0 Ruby's stack upper boundary 0xbffff1f0 Ruby's stack lower boundary 0x086032a0 System V context's stack upper boundary 0x082032a0 System V context's stack lower boundary (low memory address) As Ruby runs, the lower boundary is adjusted (by the SET_STACK_END macro) to reflect the machine stack pointer: (high memory address) 0xc1bff1f0 Ruby's stack upper boundary 0x086032a0 System V context's stack upper boundary 0x08601680 Ruby's stack lower boundary (after update by SET_STACK_END) 0x082032a0 System V context's stack lower boundary (low memory address) See the problem? Ruby's stack and the C coroutine stack do not agree. They overlap! This situation becomes worse (and causes a segfault) when the Ruby GC runs: it marks VALUEs in the Ruby stack, which currently contains all of the heap memory! Somewhere in the vast heap memory, it finds and dereferences a NULL value and BOOM! a segfault occurs. :-) To solve this problem, the ruby_bind_stack() function corrects Ruby's stack to reflect the stack boundaries of the C coroutine: (high memory address) 0x086032a0 Ruby's stack upper boundary and also System V context's stack upper boundary 0x08601680 Ruby's stack lower boundary (after update by SET_STACK_END) 0x082032a0 System V context's stack lower boundary (low memory address) Now, when the Ruby GC runs, it marks VALUEs in the correct memory region. It does not travel into heap memory and cause a segfault. That is all. Thanks for reading! ---------------------------------------- http://redmine.ruby-lang.org/issues/show/2294 ---------------------------------------- http://redmine.ruby-lang.org