-
-
Notifications
You must be signed in to change notification settings - Fork 40
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
panics in vacuum goroutines can't be handled #216
Comments
Do you have an example of a custom rule and a sample snippet of a spec that you're using to throw this panic? I want to ensure that I catch this in the right place. |
Here is a small reproducible package main
import (
"fmt"
"io"
"net/http"
"github.com/daveshanley/vacuum/model"
"github.com/daveshanley/vacuum/motor"
"github.com/daveshanley/vacuum/rulesets"
"gopkg.in/yaml.v3"
)
func read() []byte {
res, err := http.Get("https://raw.githubusercontent.com/speakeasy-api/openapi-directory/main/APIs/nexmo.com/conversation/2.0.1/openapi.yaml")
if err != nil {
panic(err)
}
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
return data
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("recovered") // won't capture the panic in the rule function
}
}()
rules := map[string]*model.Rule{
"test": {
Id: "test",
Formats: model.OAS3AllFormat,
Given: "$",
Recommended: true,
RuleCategory: model.RuleCategories[model.CategoryValidation],
Type: "validation",
Severity: model.SeverityError,
Then: model.RuleAction{
Function: "test",
},
},
}
set := &rulesets.RuleSet{
DocumentationURI: "",
Rules: rules,
Description: "",
}
motor.ApplyRulesToRuleSet(
&motor.RuleSetExecution{
RuleSet: set,
Spec: read(),
CustomFunctions: map[string]model.RuleFunction{
"test": &testRule{},
},
})
}
type testRule struct{}
func (t *testRule) GetSchema() model.RuleFunctionSchema {
return model.RuleFunctionSchema{
Name: "test",
}
}
func (d *testRule) RunRule(nodes []*yaml.Node,
context model.RuleFunctionContext,
) []model.RuleFunctionResult {
panic("run away!")
} |
Great! thank you. |
When building custom rules programatically, now you can supply a `PanicFunction` handler to `RuleSetExecution`. This allows any panic thrown in a custom function, to be caught upstream and handled appropriately.
I have created a new This function captures any panic thrown by any rule executing and you can do what you like with the panic thrown ( saveMePlease := func(r any) {
fmt.Printf("panic: saved by the bell (%v)", r)
}
motor.ApplyRulesToRuleSet(
&motor.RuleSetExecution{
PanicFunction: saveMePlease,
RuleSet: set,
Spec: read(),
CustomFunctions: map[string]model.RuleFunction{
"test": &testRule{},
},
}) Using your custom rule: type testRule struct{}
func (t *testRule) GetSchema() model.RuleFunctionSchema {
return model.RuleFunctionSchema{
Name: "test",
}
}
func (d *testRule) RunRule(nodes []*yaml.Node,
context model.RuleFunctionContext,
) []model.RuleFunctionResult {
panic("run away!")
} Will output:
|
When building custom rules programatically, now you can supply a `PanicFunction` handler to `RuleSetExecution`. This allows any panic thrown in a custom function, to be caught upstream and handled appropriately.
This will be available in |
works great thank you |
If a panic occurs in a custom rule, because it seems the document is being evaluated with goroutines these can't be caught using
recover
and so can cause crashes for a server.It would be good if vacuum can recover from panicing goroutines and then throw this panic on the main thread so then these panics can be caught by the code calling vacuum.
here is an example callstack
The text was updated successfully, but these errors were encountered: