amamcloud / go-mruby

Go (golang) bindings to mruby.
MIT License
0 stars 0 forks source link

TestMrbStackedException 테스트 segfault 해결 #1

Open k9strel opened 6 years ago

k9strel commented 6 years ago
 MRUBY_COMMIT=1.3.0 make

로 빌드 하는 경우에 한해서,

mrb.TopSelf().SingletonClass().DefineMethod("myeval", evalFunc, ArgsBlock())

또는

mrb.KernelModule().DefineMethod("myeval", evalFunc, ArgsBlock())

에서 Block을 instance_eval로 호출하면 segfault가 발생함.

1.2.0에서 발생하지 않는 걸로 봐서는 저 사이 경로에서 참조하는 코드 중 Breakable Change가 포함되어 있는 것으로 보임

k9strel commented 6 years ago
// mruby_test.go:576 부터
        evalFunc := func(m *Mrb, self *MrbValue) (Value, Value) {
                arg := m.GetArgs()[0]
                result, _ := self.CallBlock("instance_eval", arg)

                return result, nil
        }

        mrb.TopSelf().SingletonClass().DefineMethod("myeval", evalFunc, ArgsBlock())

        result, err := mrb.LoadString("myeval { raise 'foo' }")
        if err == nil {
                t.Fatal("did not error")
                return
        }

        if result != nil {
                t.Fatal("result was not cleared")
                return
        }

        mrb.Close()

여기 그 중에서도 576번째 라인부터 시작하는 evalFunc이 문제 지점임.

mrb.KernelModule().DefineMethod("myeval", evalFunc, ArgsBlock())

mrb.TopSelf().SingletonClass().DefineMethod("myeval", evalFunc, ArgsBlock())

는 양쪽 다 동일한 문제가 발생 (실제로도 같은 일을 하는 코드)

대신

        testClass = mrb.DefineClass("Test", nil)

        testClass.DefineMethod("myeval", evalFunc, ArgsBlock())

        mrb.LoadString("test = Test.new")
        result, err := mrb.LoadString("test.myeval { raise 'foo' }")

와 같이 별도의 객체를 정의하고 해당 객체를 통해서 호출 하는 경우에는 정상적으로 동작함.

astral1 commented 6 years ago

정상적으로 동작하는 경우들 목록

instance_eval을 class_eval로 변경

        evalFunc := func(m *Mrb, self *MrbValue) (Value, Value) {
                arg := m.GetArgs()[0]
                result, _ := self.CallBlock("class_eval", arg)

                return result, nil
        }

go-mruby 인터페이스를 사용하지 않음

result, err := mrb.LoadString("def myeval(&blk) instance_eval blk; end; myeval { raise 'foo' }")