From 48f887591519535589976b443bcf7a824f93c7eb Mon Sep 17 00:00:00 2001 From: Bai Yingjie Date: Fri, 16 Jun 2023 02:51:28 +0000 Subject: [PATCH] interp: recover in Eval and EvalPath Now Eval() and EvalPath() recover from internal panic and return it as error with call stacks. This fixes the case where user code calls os.Exit(1), which is converted to panic() and breaks down the program. --- interp/interp.go | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/interp/interp.go b/interp/interp.go index bb3c24392..4b9ff5e55 100644 --- a/interp/interp.go +++ b/interp/interp.go @@ -498,6 +498,14 @@ func (interp *Interpreter) resizeFrame() { // Eval evaluates Go code represented as a string. Eval returns the last result // computed by the interpreter, and a non nil error in case of failure. func (interp *Interpreter) Eval(src string) (res reflect.Value, err error) { + defer func() { + if r := recover(); r != nil { + var pc [64]uintptr + n := runtime.Callers(1, pc[:]) + err = Panic{Value: r, Callers: pc[:n], Stack: debug.Stack()} + } + }() + return interp.eval(src, "", true) } @@ -505,6 +513,14 @@ func (interp *Interpreter) Eval(src string) (res reflect.Value, err error) { // by the interpreter, and a non nil error in case of failure. // The main function of the main package is executed if present. func (interp *Interpreter) EvalPath(path string) (res reflect.Value, err error) { + defer func() { + if r := recover(); r != nil { + var pc [64]uintptr + n := runtime.Callers(1, pc[:]) + err = Panic{Value: r, Callers: pc[:n], Stack: debug.Stack()} + } + }() + if !isFile(interp.opt.filesystem, path) { _, err := interp.importSrc(mainID, path, NoTest) return res, err @@ -581,14 +597,7 @@ func (interp *Interpreter) EvalWithContext(ctx context.Context, src string) (ref done := make(chan struct{}) go func() { - defer func() { - if r := recover(); r != nil { - var pc [64]uintptr - n := runtime.Callers(1, pc[:]) - err = Panic{Value: r, Callers: pc[:n], Stack: debug.Stack()} - } - close(done) - }() + defer close(done) v, err = interp.Eval(src) }()