<mahoney>
That's a simplified example. It always fails on a "to_s".
<mahoney>
That foo() function will be called many times, and sometimes it works.
<drbrain>
should line 7 and 8 be struct RBClassWrapper?
<mahoney>
What do you mean?
<drbrain>
well, I don't know C++
<drbrain>
in C I would think the compiler would complain about not having "struct"
<mahoney>
Ah, no it's not complaining, but I'll try putting struct there. You're right, this is C++.
<mahoney>
I feel like that can't be it though.
<drbrain>
me too
<drbrain>
your use of free() feels wrong
<drbrain>
do you need to call the reconstructor for RbClassWrapper->ptr
<drbrain>
?
<drbrain>
I wonder if your object gets GC'd
<drbrain>
try creating a custom free function with printf("I was collected!\n");
<mahoney>
I do have a custom free function, but I didn't put it in the example. Things are getting freed, but not that object I don't think. Let me make sure.
<drbrain>
I don't see anything obviously wrong with this sample
<drbrain>
but since you have foo() I'm wondering if the GC is cleaning something up it shouldn't
<drbrain>
for example, if rbInstance is in a register it may get GC'd
<drbrain>
in which case you need to mark it volatile
<drbrain>
or you RB_GC_GUARD/RB_GC_GUARD_PTR
<drbrain>
you -> use
<mahoney>
I've been using rb_gc_mark to keep the Ruby instance around, should I be using RB_GC_GUARD instead?
<drbrain>
the macro and the function do separate things
<drbrain>
if MyClass has a VALUE in it then you need to provide a mark function to allow ruby to mark that value
<drbrain>
if you are writing a C/C++ function that allocates an object but stores the pointer in a register you use RB_GC_GUARD to allow the GC to see it
<drbrain>
you don't have control over which C variables get optimized away, but RB_GC_GUARD forces it to be on the stack where the GC can find and mark it
<mahoney>
MyClass doesn't hold any VALUEs, but another class holds the rbInstance. Should I be using RB_GC_GUARD in that other class?
<drbrain>
I would try it
<drbrain>
if OtherClass holds rbInstance and is wrapped for ruby, it should use rb_gc_mark
<mahoney>
OtherClass doesn't get wrapped for Ruby. It's used only in C(++)
<drbrain>
ok
<drbrain>
just to help give context to which function is used where
<drbrain>
it sounds like you don't need rb_gc_mark in your C extension
<mahoney>
Yeah, I never really understood completely what it was doing. I just knew I needed this object to stay around. So RB_GC_GUARD is what I'm supposed to be using?
<mahoney>
None of my wrapped classes hold VALUEs, but I do have non-wrapped classes that hold VALUEs.
<drbrain>
you probably need to take care in those non-wrapped classes to ensure the VALUEs live on the stack
<drbrain>
the macro is a cross-platform way of marking the variable as volatile
<mahoney>
So I don't need to mark the cMyClass as volatile, but I'll need to mark the rbInstance as volatile if I'm storing it in OtherClass. Correct?
<drbrain>
mahoney: that sounds right
<drbrain>
I don't know the right word for the type of variable cClass is (static)? but it doesn't matter
<drbrain>
cMyClass to ruby's Object, so it will be reachable by the GC
<drbrain>
(what, where did half my typing go?)
<drbrain>
cMyClass is attached to Object
idkazuma has joined #ruby-core
tenderlove has quit [Remote host closed the connection]
<mahoney>
This whole volatile thing confuses me a bit.
<drbrain>
ruby's GC walks the stack looking for pointers into the ruby heap
<drbrain>
(even values that look like pointers are considered valid, but that's unimportant your problem)
<drbrain>
when you create a new object you get a pointer to it
<drbrain>
however, it's possible that the compiler doesn't put that pointer on the stack
<drbrain>
instead it only exists in a register
<drbrain>
so when ruby walks the stack it can't see myInstance (as it was never saved there) and doesn't see any other pointers to the object, so it collects it
<mahoney>
Is Ruby walking the C stack or it's own Ruby stack?
<drbrain>
the C stack
<drbrain>
the C stack is the Ruby stack
<drbrain>
or, ruby uses the C stack
<mahoney>
Okay, that makes sense.
<drbrain>
volatile tells the compiler "I'm doing things you don't know about with this variable, so don't optimize it away"
<drbrain>
(also, this behavior of the ruby GC is one of the things that we would like to fix, but haven't yet as it is difficult to fix compatibly with existing extensions)
<mahoney>
Hmm. So do I want to store a "volatile VALUE" or a pointer "volatile VALUE*"?
<drbrain>
you just need to do VALUE rbInstance = toRB(…); RB_GC_GUARD(rbInstance);
<mahoney>
Crazy, so the "volatile" aspect remains even though I'm not using the result of RB_GC_GUARD?
<drbrain>
right
<mahoney>
Okay, would it hurt to guard every single VALUE?
<mahoney>
From what I can guess, it would just be less optimized.
<drbrain>
it wouldn't hurt, but it shouldn't be needed everywhere
<drbrain>
unfortunately I don't know enough about compilers to say for certain
<mahoney>
Hmm. After guarding everything as a test, I'm still getting the same error.
<drbrain>
dang, then my idea was wrong ☹
<mahoney>
Haha it's okay.
<drbrain>
I'm not sure what other thing could be wrong
<drbrain>
that would need to be reinitialized per VM
<mahoney>
Yeah, that is a problem.
<mahoney>
What if I don't need any extensions?
<drbrain>
I'm uncertain
<drbrain>
there may be other problems besides this one
<drbrain>
it may be that the core libraries also aren't clean in this regard
<mahoney>
Sounds dirty.
<mahoney>
Is there any reason not to skip 1.9.3 and update straight to 2.0?
<drbrain>
I don't think you'll have problems skipping 1.9.3
<mahoney>
Cool. I'll just have to figure out what to use instead of ruby_frame.
<mahoney>
I have one more question you might be able to answer. The reason I'd want multiple VMs is because I need to run arbitrary code that shouldn't know about each other. If one piece of code creates a class, then the others will have access to that class. Is there any way to prevent that other than just not assigning the class to a constant? Can I run the code in little sandboxed environments?
<mahoney>
And using Processes doesn't really fit with this application.
<drbrain>
the second argument to load allows you to create a sandbox namespace
<drbrain>
load 'foo', true
<drbrain>
if foo.rb creates classes they are created in the anonymous namespace, but you can still see other people's stuff through ObjectSpace
<drbrain>
so if you don't need to worry about cheating that might work
<drbrain>
you can do the same thing yourself with something like: Module.new.class_eval "…"
<mahoney>
Hmm, hang on a second.
<mahoney>
That sounds almost perfect.
<drbrain>
with Module.new you could inject your own framework with include/extend before invoking user code
<mahoney>
Oh...maybe it just doesn't work with blocks?
<drbrain>
maybe
<drbrain>
if I put the contents of module1 and module2 in separate files it behaves as I explained
<drbrain>
I haven't looked inside load in a while to see what the equivalent ruby is
<mahoney>
Yeah, it behaves like you said if you supply a string to class_eval as well.
<drbrain>
ok
<mahoney>
Which is good, because I'm using strings, not blocks.
<mahoney>
This is the best day ever.
<mahoney>
Seriously, thank you so much. I was half way through trying to catch class definitions in an event hook and redefining the constants under a namespace haha.
<drbrain>
:D
<mahoney>
And thanks for the help with the class path problem. Hopefully updating will help that.
<mahoney>
Off the top of your head, is there a way to stop the code from cheating and looking at the ObjectSpace?
<drbrain>
removing the ObjectSpace constant might work
<mahoney>
Well that makes sense. I'll look into it.
<mahoney>
Dr. Brain, you have lived up to your name.
<drbrain>
sorry I couldn't help fix the to_s probelm
<mahoney>
If updating doesn't fix it, then I'll just come back to haunt you haha.
<drbrain>
heh
davidbalbert is now known as davidbalber|away
<mahoney>
Or maybe I'm just not using RB_GC_GUARD correctly.
<mahoney>
I tried saying RB_GC_GUARD(instance) in that toRB function. That way, every single one of my wrapped classes gets guarded. Still no luck.
<drbrain>
it's per-function, not per object
<drbrain>
so it would need to appear in foo()
<mahoney>
Hmm...
<mahoney>
Let me find the real foo()
<znz_v>
biff: [ruby-changes:27825] marcandRe: r39877 (trunk): * array.c: Avoid zip bug by not using obsolete rb_check_block_call [Bug #8153] - http://mla.n-z.jp/?ruby-changes=27825