diff options
| author | Russ Cox <rsc@golang.org> | 2024-05-17 12:07:15 -0400 |
|---|---|---|
| committer | Gopher Robot <gobot@golang.org> | 2024-05-23 02:32:19 +0000 |
| commit | ff2070d9398aff1c44691a90761eb35ea3cd4601 (patch) | |
| tree | 77cb849fc27f0348ca652dd162ae3fbf9346ee33 /src/runtime | |
| parent | fd1363240ac22583125d43d8e15f130f02a7659b (diff) | |
| download | go-ff2070d9398aff1c44691a90761eb35ea3cd4601.tar.xz | |
runtime: move exit hooks into internal/runtime/exithook
This removes a //go:linkname usage in the coverage implementation.
For #67401.
Change-Id: I0602172c7e372a84465160dbf46d9fa371582fff
Reviewed-on: https://go-review.googlesource.com/c/go/+/586259
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Diffstat (limited to 'src/runtime')
| -rw-r--r-- | src/runtime/exithook.go | 68 | ||||
| -rw-r--r-- | src/runtime/linkname.go | 3 | ||||
| -rw-r--r-- | src/runtime/proc.go | 7 | ||||
| -rw-r--r-- | src/runtime/testdata/testexithooks/testexithooks.go | 34 |
4 files changed, 23 insertions, 89 deletions
diff --git a/src/runtime/exithook.go b/src/runtime/exithook.go deleted file mode 100644 index 37d68bd767..0000000000 --- a/src/runtime/exithook.go +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2022 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 runtime - -// addExitHook registers the specified function 'f' to be run at -// program termination (e.g. when someone invokes os.Exit(), or when -// main.main returns). Hooks are run in reverse order of registration: -// first hook added is the last one run. -// -// CAREFUL: the expectation is that addExitHook should only be called -// from a safe context (e.g. not an error/panic path or signal -// handler, preemption enabled, allocation allowed, write barriers -// allowed, etc), and that the exit function 'f' will be invoked under -// similar circumstances. That is the say, we are expecting that 'f' -// uses normal / high-level Go code as opposed to one of the more -// restricted dialects used for the trickier parts of the runtime. -func addExitHook(f func(), runOnNonZeroExit bool) { - exitHooks.hooks = append(exitHooks.hooks, exitHook{f: f, runOnNonZeroExit: runOnNonZeroExit}) -} - -// exitHook stores a function to be run on program exit, registered -// by the utility runtime.addExitHook. -type exitHook struct { - f func() // func to run - runOnNonZeroExit bool // whether to run on non-zero exit code -} - -// exitHooks stores state related to hook functions registered to -// run when program execution terminates. -var exitHooks struct { - hooks []exitHook - runningExitHooks bool -} - -// runExitHooks runs any registered exit hook functions (funcs -// previously registered using runtime.addExitHook). Here 'exitCode' -// is the status code being passed to os.Exit, or zero if the program -// is terminating normally without calling os.Exit. -func runExitHooks(exitCode int) { - if exitHooks.runningExitHooks { - throw("internal error: exit hook invoked exit") - } - exitHooks.runningExitHooks = true - - runExitHook := func(f func()) (caughtPanic bool) { - defer func() { - if x := recover(); x != nil { - caughtPanic = true - } - }() - f() - return - } - - for i := range exitHooks.hooks { - h := exitHooks.hooks[len(exitHooks.hooks)-i-1] - if exitCode != 0 && !h.runOnNonZeroExit { - continue - } - if caughtPanic := runExitHook(h.f); caughtPanic { - throw("internal error: exit hook invoked panic") - } - } - exitHooks.hooks = nil - exitHooks.runningExitHooks = false -} diff --git a/src/runtime/linkname.go b/src/runtime/linkname.go index 42d8d245a6..19318cd9a9 100644 --- a/src/runtime/linkname.go +++ b/src/runtime/linkname.go @@ -29,9 +29,6 @@ import _ "unsafe" //go:linkname overflowError //go:linkname divideError -// used in runtime/coverage and in tests -//go:linkname addExitHook - // used in tests //go:linkname extraMInUse //go:linkname getm diff --git a/src/runtime/proc.go b/src/runtime/proc.go index 68296bd1e4..c5bf537a75 100644 --- a/src/runtime/proc.go +++ b/src/runtime/proc.go @@ -10,6 +10,7 @@ import ( "internal/goarch" "internal/goos" "internal/runtime/atomic" + "internal/runtime/exithook" "internal/stringslite" "runtime/internal/sys" "unsafe" @@ -309,6 +310,12 @@ func os_beforeExit(exitCode int) { } } +func runExitHooks(code int) { + if err := exithook.Run(code); err != nil { + throw(err.Error()) + } +} + // start forcegc helper goroutine func init() { go forcegchelper() diff --git a/src/runtime/testdata/testexithooks/testexithooks.go b/src/runtime/testdata/testexithooks/testexithooks.go index ceb3326c4f..151b5dc62b 100644 --- a/src/runtime/testdata/testexithooks/testexithooks.go +++ b/src/runtime/testdata/testexithooks/testexithooks.go @@ -7,6 +7,7 @@ package main import ( "flag" "os" + "internal/runtime/exithook" _ "unsafe" ) @@ -30,22 +31,19 @@ func main() { } } -//go:linkname runtime_addExitHook runtime.addExitHook -func runtime_addExitHook(f func(), runOnNonZeroExit bool) - func testSimple() { f1 := func() { println("foo") } f2 := func() { println("bar") } - runtime_addExitHook(f1, false) - runtime_addExitHook(f2, false) + exithook.Add(exithook.Hook{F: f1}) + exithook.Add(exithook.Hook{F: f2}) // no explicit call to os.Exit } func testGoodExit() { f1 := func() { println("apple") } f2 := func() { println("orange") } - runtime_addExitHook(f1, false) - runtime_addExitHook(f2, false) + exithook.Add(exithook.Hook{F: f1}) + exithook.Add(exithook.Hook{F: f2}) // explicit call to os.Exit os.Exit(0) } @@ -56,11 +54,11 @@ func testBadExit() { f3 := func() { println("blek") } f4 := func() { println("blub") } f5 := func() { println("blat") } - runtime_addExitHook(f1, false) - runtime_addExitHook(f2, true) - runtime_addExitHook(f3, false) - runtime_addExitHook(f4, true) - runtime_addExitHook(f5, false) + exithook.Add(exithook.Hook{F: f1}) + exithook.Add(exithook.Hook{F: f2, RunOnFailure: true}) + exithook.Add(exithook.Hook{F: f3}) + exithook.Add(exithook.Hook{F: f4, RunOnFailure: true}) + exithook.Add(exithook.Hook{F: f5}) os.Exit(1) } @@ -68,9 +66,9 @@ func testPanics() { f1 := func() { println("ok") } f2 := func() { panic("BADBADBAD") } f3 := func() { println("good") } - runtime_addExitHook(f1, true) - runtime_addExitHook(f2, true) - runtime_addExitHook(f3, true) + exithook.Add(exithook.Hook{F: f1, RunOnFailure: true}) + exithook.Add(exithook.Hook{F: f2, RunOnFailure: true}) + exithook.Add(exithook.Hook{F: f3, RunOnFailure: true}) os.Exit(0) } @@ -78,8 +76,8 @@ func testHookCallsExit() { f1 := func() { println("ok") } f2 := func() { os.Exit(1) } f3 := func() { println("good") } - runtime_addExitHook(f1, true) - runtime_addExitHook(f2, true) - runtime_addExitHook(f3, true) + exithook.Add(exithook.Hook{F: f1, RunOnFailure: true}) + exithook.Add(exithook.Hook{F: f2, RunOnFailure: true}) + exithook.Add(exithook.Hook{F: f3, RunOnFailure: true}) os.Exit(1) } |
