Hello,
I have a C program that embeds Ruby 1.9.1. When I call into the Ruby
interpreter, and Ruby yield()s an object from a fiber back to my C
program, then later call back the object from C, which causes the fiber
to be resume()d, it causes a Ruby error with message "fiber called
across trap".
If I comment out the relevant code in Ruby's cont.c (lines 876-877), the
above case works fine. My question is, what is the danger of not doing
the "fiber called across trap" check, or what is the badness that this
check is protecting from? I know nothing about the Ruby VM, so go easy
on me. :-)
If you want to know why I'm doing this, please read on. If this is a
dumb way to be doing things, can anyone tell me what I should be doing
instead of resuming fibers across C calls?
--8<----
First, my C program calls out to the Ruby interpreter with something
like
rb_funcall(obj, rb_intern("call"), argc, args...);
Ruby does some "business logic" processing then returns a Ruby array to
C (actually yield()ed from a fiber) like this:
[REQ_DB, query_str, callback_obj, callback_method]
The C program (the "server") then saves the pointers to callback_obj and
callback_method, turns query_str into a query, and sends it to our
internal database in a non-blocking fashion.
[There are also other response types, like REQ_HTTP (which performs a
non-blocking HTTP request to a backend web service).]
On receiving the response from the database, the server then calls Ruby
back with the result of the query as a Ruby string:
rb_funcall(callback_obj, SYM2ID(callback_method),
INT2FIX(db_result_code),
rb_str_new(db_result_start,
db_result_end-db_result_start));
This callback results in a call to resume() on the fiber that yielded
(and was wrapped and docked into a Hash of in-flight requests).
The intention is that in Ruby we can write code that looks like:
def dostuff
return something_based_on(req_db(query_string1),
req_db(query_string2))
end
rather than
def dostuff
req_db(query_string1, self, :handle_query1)
end
def handle_query1(resultset1)
@resultset1 = resultset1 # ugh.
req_db(query_string2, self, :handle_query2)
end
def handle_query2(resultset2)
return something_based_on(@resultset1, resultset2) # ugh!
end
Thanks for reading,
James
Please consider the environment before printing this email :-)
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they are
addressed. If you have received this email in error please notify the
sender immediately then delete this email. Any views expressed in this
email are solely that of the individual and not representative of the
company as a whole.
Media Molecule Limited
Company Reg No 5665849
Registered in England.
on 17.08.2009 18:44