Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

mruby.Run does not work with a Proc returned from LoadString #23

Open
mikesimons opened this issue Mar 7, 2016 · 6 comments
Open

mruby.Run does not work with a Proc returned from LoadString #23

mikesimons opened this issue Mar 7, 2016 · 6 comments

Comments

@mikesimons
Copy link
Contributor

mrb := NewMrb()
defer mrb.Close()

proc, _ := mrb.LoadString(`
    Proc.new do
        puts 1
    end
`)

val, err := mrb.Run(proc, nil)

fmt.Printf("%#v, %#v", val, err)

Expected: Prints "1", returns nil, nil
Actual: (_mruby.MrbValue)(nil), &mruby.Exception{MrbValue:(_mruby.MrbValue)(0xc8200920e0), cachedString:"unexpected return"}

For some reason mruby.Run does not work with a Proc returned from mruby.LoadString. There may be good technical reasons (though I can't think of what they might be) but this surprised me. The error unexpected return is also non-obvious as there is no return injected anywhere AFAICT.

It is necessary to use something like the following to create a Proc that works with mruby.Run:

mrb := NewMrb()
defer mrb.Close()

parser := NewParser(mrb)
defer parser.Close()

context := NewCompileContext(mrb)
defer context.Close()

parser.Parse(`puts 1`, context)
proc := parser.GenerateCode()

val, err := mrb.Run(proc, nil)
fmt.Printf("%#v, %#v", val, err)

This works as expected. Drilling down in to the differences between the MrbValues generated with these two approaches should be sufficient to determine a cause (and potential solution).

@mitchellh
Copy link
Owner

Pretty odd. I expect its some weirdness with the C API. Steps forward would be:

  1. Determine if mrb_run is supposed to work with procs at all.
  2. If yes, fix it!
  3. If no, ask ourselves why? And determine if go-mruby should "just work".

@mitchellh
Copy link
Owner

(Note: not telling you you have to do this, just posting that thats what the steps are in general)

@erikh
Copy link
Collaborator

erikh commented Oct 5, 2016

while I was trying to verify this, I ran into a full panic with the following ruby:

def foo
end

The return value is indeed the foo func yet this trace occurs on a recent version of master:

[fail:1][75] erikh@islay erikh/ruby-builder% go run ~/test.go                                [14:34]
foo
fatal error: unexpected signal during runtime execution
[signal SIGSEGV: segmentation violation code=0x1 addr=0x2a5 pc=0x40c3bf2]

runtime stack:
runtime.throw(0x4135538, 0x2a)
        /usr/local/Cellar/go/1.7.1/libexec/src/runtime/panic.go:566 +0x95
runtime.sigpanic()
        /usr/local/Cellar/go/1.7.1/libexec/src/runtime/sigpanic_unix.go:12 +0x2cc

goroutine 1 [syscall, locked to thread]:
runtime.cgocall(0x408a750, 0xc42004fe18, 0x0)
        /usr/local/Cellar/go/1.7.1/libexec/src/runtime/cgocall.go:131 +0x110 fp=0xc42004fdc8 sp=0xc42004fd88
github.com/mitchellh/go-mruby._Cfunc_mrb_run(0x4402850, 0x28d, 0x48084a0, 0x8, 0x0, 0x0)
        ??:0 +0x57 fp=0xc42004fe18 sp=0xc42004fdc8
github.com/mitchellh/go-mruby.(*Mrb).Run(0xc420086018, 0x41b2440, 0xc420088060, 0x41b2440, 0xc420088080, 0x4, 0x0, 0x0)
        /Users/erikh/src/github.com/mitchellh/go-mruby/mruby.go:193 +0x1b4 fp=0xc42004feb8 sp=0xc42004fe18
main.main()
        /Users/erikh/test.go:20 +0x11d fp=0xc42004ff48 sp=0xc42004feb8
runtime.main()
        /usr/local/Cellar/go/1.7.1/libexec/src/runtime/proc.go:183 +0x1f4 fp=0xc42004ffa0 sp=0xc42004ff48
runtime.goexit()
        /usr/local/Cellar/go/1.7.1/libexec/src/runtime/asm_amd64.s:2086 +0x1 fp=0xc42004ffa8 sp=0xc42004ffa0

goroutine 17 [syscall, locked to thread]:
runtime.goexit()
        /usr/local/Cellar/go/1.7.1/libexec/src/runtime/asm_amd64.s:2086 +0x1
exit status 2

@mikesimons
Copy link
Contributor Author

mikesimons commented Oct 6, 2016

@erikh I've replicated it but given that this code already isn't behaving as we anticipated I'm not entirely surprised.

My test case was:

mrb := mruby.NewMrb()
defer mrb.Close()

result, err := mrb.LoadString(`
def foo
end
`)

// mrb.Run(result, nil) // Causes SIGSEGV

fmt.Printf("Result: %#v, %s\n", result, err)

This printed:

Result: &mruby.MrbValue{value:mruby._Ctype_struct_mrb_value{value:[8]uint8{0x8d, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, tt:0x4, _:[4]uint8{0x0, 0x0, 0x0, 0x0}}, state:(*mruby._Ctype_struct_mrb_state)(0x2578760)}, %!s(<nil>)

tt:0x4 field of mrb_value indicates that result contains an MRB_TT_SYMBOL

IRB behaves similarly (returning a symbol from a function declaration):

> irb
irb(main):001:0> def foo
irb(main):002:1> end
=> :foo

I think we'd need to expose / use mrb_f_send to make your test work.

@erikh
Copy link
Collaborator

erikh commented Oct 6, 2016

makes sense. I'll see what I can do this week.

On 6 Oct 2016, at 6:53, Mike Simons wrote:

@erikh I've replicated it but given that this code already isn't
behaving as we anticipated I'm not entirely surprised.

My test case was:

mrb := mruby.NewMrb()
defer mrb.Close()

result, err := mrb.LoadString(`
def foo
end
`)

// mrb.Run(result, nil) // Causes SIGSEGV

fmt.Printf("Result: %#v, %s\n", result, err)

This printed:

Result: 
&mruby.MrbValue{value:mruby._Ctype_struct_mrb_value{value:[8]uint8{0x8d, 
0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, tt:0x4, _:[4]uint8{0x0, 0x0, 0x0, 
0x0}}, state:(*mruby._Ctype_struct_mrb_state)(0x2578760)}, %!s(<nil>)

tt:0x4 field of mrb_value indicates that result contains an
mrb_value of type
MRB_TT_SYMBOL

IRB behaves similarly (returning a symbol from a function
declaration):

> irb
irb(main):001:0> def foo
irb(main):002:1> end
=> :foo

I think we'd need to expose / use
mrb_f_send
to make your test work.

You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#23 (comment)

@mikesimons
Copy link
Contributor Author

Just a note; since such an easy mistake to make can cause a segfault, we should probably inspect the mrbvalue and ensure it's a proc before handing it over to C. Might also be interesting to try this with a more recent version of mruby (I tested against the version in the makefile)

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

No branches or pull requests

3 participants