Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash when eval "Fiber.yield" #3415

Closed
i110 opened this issue Jan 25, 2017 · 6 comments
Closed

Crash when eval "Fiber.yield" #3415

i110 opened this issue Jan 25, 2017 · 6 comments

Comments

@i110
Copy link
Contributor

i110 commented Jan 25, 2017

The following code causes a crash with a SEGV.

Fiber.new { eval "Fiber.yield" }.resume

Is this possible in mruby?

@kazuho
Copy link
Contributor

kazuho commented Jan 25, 2017

For context, this is a bug that we ran into while looking for a way to load and evaluate a code within a fiber.

In H2O, we would like to evaluate mruby code that defines a Rack handler within a fiber, so that when a blocking operation is triggered within the evaluation Fiber.yield could be used to transfer that operation into C code.

Essentially, we would like to allow users to write something like the snippet below, which will be evaluated within a fiber (note: join methods calls Fiber.yield to delegate network operations to the main fiber).

# cache the response from http://upstream, and use it for every request
cached_resp = http_request("http://upstream/").join[2].join
Proc.new do |env|
    [200, [], [cached_resp]]
end

@matz
Copy link
Member

matz commented Jan 25, 2017

It's not possible, mruby's fiber cannot cross C function boundaries, although causing SEGV is a bug.

@kazuho
Copy link
Contributor

kazuho commented Jan 26, 2017

@matz Thank you for the clarification. The reasoning sounds totally reasonable that you cannot call yield from an eval-ed script running in a fiber due to C function boundaries.

OTOH, may I ask if you have any idea that we could solve the issue? As stated in #3415 (comment) what we want to do is to evaluate user-specified script in a child fiber. We are more than happy to write such solution in C.

@i110
Copy link
Contributor Author

i110 commented Feb 3, 2017

Another question: are there standard ways to generate Proc's instance from mruby source code?
(sorry for changing the topic from this issue)

We found that we can address the issue described in #3415 (comment) in another way, by passing the compiled code to some preparing method as a proc. Like the following, prepare_app method calls that compiled proc in a fiber (because compiled_proc may call Fiber.yield).

def prepare_app(compiled_proc)
  Fiber.new do
      compiled_proc.call
  end.resume
end

But as far as I see the mruby API, there seems to be no ways to do it. mrb_generate_code returns struct RProc*, but can I convert it to a Proc's instance? I tried mrb_obj_value(mrb_generate_code(mrb, parser_state)), but it failed when that proc is called. Am I missing something?

Thank you in advance.

@i110 i110 closed this as completed Feb 3, 2017
@i110
Copy link
Contributor Author

i110 commented Feb 3, 2017

Sorry, I mistakenly closed this issue

@i110 i110 reopened this Feb 3, 2017
@matz matz closed this as completed in 48e0bbb Feb 4, 2017
@matz
Copy link
Member

matz commented Feb 4, 2017

48e0bbb allows you to call Fiber.yield from within eval().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants