diff --git a/src/cmd/vet/lostcancel.go b/src/cmd/vet/lostcancel.go index ee0342035fe..496e87a5e04 100644 --- a/src/cmd/vet/lostcancel.go +++ b/src/cmd/vet/lostcancel.go @@ -104,6 +104,11 @@ func checkLostCancel(f *File, node ast.Node) { var sig *types.Signature switch node := node.(type) { case *ast.FuncDecl: + if node.Name.Name == "main" && node.Recv == nil && f.file.Name.Name == "main" { + // Returning from main.main terminates the process, + // so there's no need to cancel contexts. + return + } obj := f.pkg.defs[node.Name] if obj == nil { return // type error (e.g. duplicate function declaration) diff --git a/src/cmd/vet/testdata/lostcancel.go b/src/cmd/vet/testdata/lostcancel.go index b7549c00511..408bed51228 100644 --- a/src/cmd/vet/testdata/lostcancel.go +++ b/src/cmd/vet/testdata/lostcancel.go @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -package testdata +package main import ( "context" @@ -33,6 +33,12 @@ func _() { ctx, _ = context.WithDeadline() // ERROR "the cancel function returned by context.WithDeadline should be called, not discarded, to avoid a context leak" } +// Return from main is handled specially. +// Since the program exits, there's no need to call cancel. +func main() { + var ctx, cancel = context.WithCancel() +} + func _() { ctx, cancel := context.WithCancel() defer cancel() // ok