go.tools/go/pointer: recover from panic in Analyse and return an error.
This is to avoid an internal error in pointer analysis from bringing down a long-lived application such as godoc. LGTM=crawshaw R=crawshaw CC=golang-codereviews https://golang.org/cl/68930046
This commit is contained in:
parent
d15a452238
commit
c509cf123c
|
|
@ -12,6 +12,7 @@ import (
|
|||
"io"
|
||||
"os"
|
||||
"reflect"
|
||||
"runtime/debug"
|
||||
|
||||
"code.google.com/p/go.tools/go/callgraph"
|
||||
"code.google.com/p/go.tools/go/ssa"
|
||||
|
|
@ -286,7 +287,19 @@ func (a *analysis) computeTrackBits() {
|
|||
// Analyze runs the pointer analysis with the scope and options
|
||||
// specified by config, and returns the (synthetic) root of the callgraph.
|
||||
//
|
||||
func Analyze(config *Config) *Result {
|
||||
// Pointer analysis of a transitively closed well-typed program should
|
||||
// always succeed. An error can occur only due to an internal bug.
|
||||
//
|
||||
func Analyze(config *Config) (result *Result, err error) {
|
||||
stage := "setup"
|
||||
defer func() {
|
||||
if p := recover(); p != nil {
|
||||
err = fmt.Errorf("internal error in pointer analysis %s: %v (please report this bug)", stage, p)
|
||||
fmt.Fprintln(os.Stderr, "Internal panic in pointer analysis:")
|
||||
debug.PrintStack()
|
||||
}
|
||||
}()
|
||||
|
||||
a := &analysis{
|
||||
config: config,
|
||||
log: config.Log,
|
||||
|
|
@ -318,7 +331,7 @@ func Analyze(config *Config) *Result {
|
|||
// (This only checks that the package scope is complete,
|
||||
// not that func bodies exist, but it's a good signal.)
|
||||
if !pkg.Object.Complete() {
|
||||
panic(fmt.Sprintf(`pointer analysis requires a complete program yet package %q was incomplete (set loader.Config.SourceImports during loading)`, pkg.Object.Path()))
|
||||
return nil, fmt.Errorf(`pointer analysis requires a complete program yet package %q was incomplete (set loader.Config.SourceImports during loading)`, pkg.Object.Path())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -347,6 +360,7 @@ func Analyze(config *Config) *Result {
|
|||
}
|
||||
a.computeTrackBits()
|
||||
|
||||
stage = "constraint generation"
|
||||
a.generate()
|
||||
|
||||
if a.log != nil {
|
||||
|
|
@ -362,8 +376,10 @@ func Analyze(config *Config) *Result {
|
|||
fmt.Fprintf(a.log, "# nodes:\t%d\n", len(a.nodes))
|
||||
}
|
||||
|
||||
//a.optimize()
|
||||
// stage = "constraint optimization"
|
||||
// a.optimize()
|
||||
|
||||
stage = "solver"
|
||||
a.solve()
|
||||
|
||||
if a.log != nil {
|
||||
|
|
@ -376,6 +392,7 @@ func Analyze(config *Config) *Result {
|
|||
}
|
||||
|
||||
// Create callgraph.Nodes in deterministic order.
|
||||
stage = "callgraph construction"
|
||||
if cg := a.result.CallGraph; cg != nil {
|
||||
for _, caller := range a.cgnodes {
|
||||
cg.CreateNode(caller.fn)
|
||||
|
|
@ -391,7 +408,7 @@ func Analyze(config *Config) *Result {
|
|||
}
|
||||
}
|
||||
|
||||
return a.result
|
||||
return a.result, nil
|
||||
}
|
||||
|
||||
// callEdge is called for each edge in the callgraph.
|
||||
|
|
|
|||
|
|
@ -79,7 +79,10 @@ func main() {
|
|||
config.AddQuery(Cfm)
|
||||
|
||||
// Run the pointer analysis.
|
||||
result := pointer.Analyze(config)
|
||||
result, err := pointer.Analyze(config)
|
||||
if err != nil {
|
||||
panic(err) // internal error in pointer analysis
|
||||
}
|
||||
|
||||
// Find edges originating from the main package.
|
||||
// By converting to strings, we de-duplicate nodes
|
||||
|
|
|
|||
|
|
@ -307,7 +307,10 @@ func doOneInput(input, filename string) bool {
|
|||
}
|
||||
}()
|
||||
|
||||
result := pointer.Analyze(config)
|
||||
result, err := pointer.Analyze(config)
|
||||
if err != nil {
|
||||
panic(err) // internal error in pointer analysis
|
||||
}
|
||||
|
||||
// Check the expectations.
|
||||
for _, e := range exps {
|
||||
|
|
|
|||
|
|
@ -464,7 +464,11 @@ func buildSSA(o *Oracle) {
|
|||
|
||||
// ptrAnalysis runs the pointer analysis and returns its result.
|
||||
func ptrAnalysis(o *Oracle) *pointer.Result {
|
||||
return pointer.Analyze(&o.ptaConfig)
|
||||
result, err := pointer.Analyze(&o.ptaConfig)
|
||||
if err != nil {
|
||||
panic(err) // pointer analysis internal error
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// unparen returns e with any enclosing parentheses stripped.
|
||||
|
|
|
|||
Loading…
Reference in New Issue