From 4e34152f16764ffb54b96842e6a72195df6e2d07 Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 9 Nov 2018 13:09:17 -0500 Subject: [PATCH] cmd/vet: lostcancel: suppress the check in the main.main function When main.main returns, the process exits, so there's no need to cancel contexts. This CL was originally reviewed as https://go-review.googlesource.com/c/go/+/106915 and then retried in https://go-review.googlesource.com/c/go/+/148758 but then reverted due to an embarrassing sequence of careless moves. Change-Id: Icdee0650996a442023e030697f10d2c31fd5fdff Reviewed-on: https://go-review.googlesource.com/c/148877 Run-TryBot: Alan Donovan Run-TryBot: Michael Matloob TryBot-Result: Gobot Gobot Reviewed-by: Michael Matloob --- go/analysis/passes/lostcancel/lostcancel.go | 10 +++++-- .../passes/lostcancel/lostcancel_test.go | 2 +- .../passes/lostcancel/testdata/src/b/b.go | 26 +++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) create mode 100644 go/analysis/passes/lostcancel/testdata/src/b/b.go diff --git a/go/analysis/passes/lostcancel/lostcancel.go b/go/analysis/passes/lostcancel/lostcancel.go index fcf9f553..996ecc4d 100644 --- a/go/analysis/passes/lostcancel/lostcancel.go +++ b/go/analysis/passes/lostcancel/lostcancel.go @@ -132,11 +132,17 @@ func runFunc(pass *analysis.Pass, node ast.Node) { var sig *types.Signature switch node := node.(type) { case *ast.FuncDecl: - g = cfgs.FuncDecl(node) sig, _ = pass.TypesInfo.Defs[node.Name].Type().(*types.Signature) + if node.Name.Name == "main" && sig.Recv() == nil && pass.Pkg.Name() == "main" { + // Returning from main.main terminates the process, + // so there's no need to cancel contexts. + return + } + g = cfgs.FuncDecl(node) + case *ast.FuncLit: - g = cfgs.FuncLit(node) sig, _ = pass.TypesInfo.Types[node.Type].Type.(*types.Signature) + g = cfgs.FuncLit(node) } if sig == nil { return // missing type information diff --git a/go/analysis/passes/lostcancel/lostcancel_test.go b/go/analysis/passes/lostcancel/lostcancel_test.go index 5fe817b3..a1d8f854 100644 --- a/go/analysis/passes/lostcancel/lostcancel_test.go +++ b/go/analysis/passes/lostcancel/lostcancel_test.go @@ -13,5 +13,5 @@ import ( func Test(t *testing.T) { testdata := analysistest.TestData() - analysistest.Run(t, testdata, lostcancel.Analyzer, "a") + analysistest.Run(t, testdata, lostcancel.Analyzer, "a", "b") } diff --git a/go/analysis/passes/lostcancel/testdata/src/b/b.go b/go/analysis/passes/lostcancel/testdata/src/b/b.go new file mode 100644 index 00000000..18ef0348 --- /dev/null +++ b/go/analysis/passes/lostcancel/testdata/src/b/b.go @@ -0,0 +1,26 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import "context" + +// Return from main is handled specially. +// Since the program exits, there's no need to call cancel. +func main() { + _, cancel := context.WithCancel(nil) + if maybe { + cancel() + } +} + +func notMain() { + _, cancel := context.WithCancel(nil) // want "cancel function.*not used" + + if maybe { + cancel() + } +} // want "return statement.*reached without using the cancel" + +var maybe bool