mirror of
https://github.com/golang/go.git
synced 2025-05-05 23:53:05 +00:00
runtime: rename runfinq to runFinalizersAndCleanups
Users see this frame in tracebacks and it serves as a hint that what is running here is a finalizer or cleanup. But runfinq is a rather dense name. We can give it a more obvious name to help users realize what it is. For #73011. Change-Id: I6a6a636ce9a493fd00d4b4c60c23f2b1c96d3568 Reviewed-on: https://go-review.googlesource.com/c/go/+/660296 Auto-Submit: Michael Pratt <mpratt@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
This commit is contained in:
parent
9c88db5f1e
commit
4f11f8ff7d
@ -27,7 +27,7 @@ var funcIDs = map[string]abi.FuncID{
|
|||||||
"morestack": abi.FuncID_morestack,
|
"morestack": abi.FuncID_morestack,
|
||||||
"mstart": abi.FuncID_mstart,
|
"mstart": abi.FuncID_mstart,
|
||||||
"panicwrap": abi.FuncID_panicwrap,
|
"panicwrap": abi.FuncID_panicwrap,
|
||||||
"runfinq": abi.FuncID_runfinq,
|
"runFinalizersAndCleanups": abi.FuncID_runFinalizersAndCleanups,
|
||||||
"sigpanic": abi.FuncID_sigpanic,
|
"sigpanic": abi.FuncID_sigpanic,
|
||||||
"systemstack_switch": abi.FuncID_systemstack_switch,
|
"systemstack_switch": abi.FuncID_systemstack_switch,
|
||||||
"systemstack": abi.FuncID_systemstack,
|
"systemstack": abi.FuncID_systemstack,
|
||||||
|
@ -56,7 +56,7 @@ const (
|
|||||||
FuncID_mstart
|
FuncID_mstart
|
||||||
FuncID_panicwrap
|
FuncID_panicwrap
|
||||||
FuncID_rt0_go
|
FuncID_rt0_go
|
||||||
FuncID_runfinq
|
FuncID_runFinalizersAndCleanups
|
||||||
FuncID_runtime_main
|
FuncID_runtime_main
|
||||||
FuncID_sigpanic
|
FuncID_sigpanic
|
||||||
FuncID_systemstack
|
FuncID_systemstack
|
||||||
|
@ -1102,31 +1102,32 @@ func TestNetpollWaiters(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The runtime.runfinq frame should appear in panics, even if runtime frames
|
// The runtime.runFinalizersAndCleanups frame should appear in panics, even if
|
||||||
// are normally hidden (GOTRACEBACK=all).
|
// runtime frames are normally hidden (GOTRACEBACK=all).
|
||||||
func TestFinalizerDeadlockPanic(t *testing.T) {
|
func TestFinalizerDeadlockPanic(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GOTRACEBACK=all", "GO_TEST_FINALIZER_DEADLOCK=panic")
|
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GOTRACEBACK=all", "GO_TEST_FINALIZER_DEADLOCK=panic")
|
||||||
|
|
||||||
want := "runtime.runfinq()"
|
want := "runtime.runFinalizersAndCleanups()"
|
||||||
if !strings.Contains(output, want) {
|
if !strings.Contains(output, want) {
|
||||||
t.Errorf("output does not contain %q:\n%s", want, output)
|
t.Errorf("output does not contain %q:\n%s", want, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The runtime.runfinq frame should appear in runtime.Stack, even though
|
// The runtime.runFinalizersAndCleanups frame should appear in runtime.Stack,
|
||||||
// runtime frames are normally hidden.
|
// even though runtime frames are normally hidden.
|
||||||
func TestFinalizerDeadlockStack(t *testing.T) {
|
func TestFinalizerDeadlockStack(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=stack")
|
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=stack")
|
||||||
|
|
||||||
want := "runtime.runfinq()"
|
want := "runtime.runFinalizersAndCleanups()"
|
||||||
if !strings.Contains(output, want) {
|
if !strings.Contains(output, want) {
|
||||||
t.Errorf("output does not contain %q:\n%s", want, output)
|
t.Errorf("output does not contain %q:\n%s", want, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The runtime.runfinq frame should appear in goroutine profiles.
|
// The runtime.runFinalizersAndCleanups frame should appear in goroutine
|
||||||
|
// profiles.
|
||||||
func TestFinalizerDeadlockPprofProto(t *testing.T) {
|
func TestFinalizerDeadlockPprofProto(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_proto")
|
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_proto")
|
||||||
@ -1139,7 +1140,7 @@ func TestFinalizerDeadlockPprofProto(t *testing.T) {
|
|||||||
t.Fatalf("Error parsing proto output: %v", err)
|
t.Fatalf("Error parsing proto output: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
want := "runtime.runfinq"
|
want := "runtime.runFinalizersAndCleanups"
|
||||||
for _, s := range p.Sample {
|
for _, s := range p.Sample {
|
||||||
for _, loc := range s.Location {
|
for _, loc := range s.Location {
|
||||||
for _, line := range loc.Line {
|
for _, line := range loc.Line {
|
||||||
@ -1154,23 +1155,25 @@ func TestFinalizerDeadlockPprofProto(t *testing.T) {
|
|||||||
t.Errorf("Profile does not contain %q:\n%s", want, p)
|
t.Errorf("Profile does not contain %q:\n%s", want, p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The runtime.runfinq frame should appear in goroutine profiles (debug=1).
|
// The runtime.runFinalizersAndCleanups frame should appear in goroutine
|
||||||
|
// profiles (debug=1).
|
||||||
func TestFinalizerDeadlockPprofDebug1(t *testing.T) {
|
func TestFinalizerDeadlockPprofDebug1(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug1")
|
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug1")
|
||||||
|
|
||||||
want := "runtime.runfinq+"
|
want := "runtime.runFinalizersAndCleanups+"
|
||||||
if !strings.Contains(output, want) {
|
if !strings.Contains(output, want) {
|
||||||
t.Errorf("output does not contain %q:\n%s", want, output)
|
t.Errorf("output does not contain %q:\n%s", want, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The runtime.runfinq frame should appear in goroutine profiles (debug=2).
|
// The runtime.runFinalizersAndCleanups frame should appear in goroutine
|
||||||
|
// profiles (debug=2).
|
||||||
func TestFinalizerDeadlockPprofDebug2(t *testing.T) {
|
func TestFinalizerDeadlockPprofDebug2(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug2")
|
output := runTestProg(t, "testprog", "FinalizerDeadlock", "GO_TEST_FINALIZER_DEADLOCK=pprof_debug2")
|
||||||
|
|
||||||
want := "runtime.runfinq()"
|
want := "runtime.runFinalizersAndCleanups()"
|
||||||
if !strings.Contains(output, want) {
|
if !strings.Contains(output, want) {
|
||||||
t.Errorf("output does not contain %q:\n%s", want, output)
|
t.Errorf("output does not contain %q:\n%s", want, output)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +164,7 @@ func wakefing() *g {
|
|||||||
func createfing() {
|
func createfing() {
|
||||||
// start the finalizer goroutine exactly once
|
// start the finalizer goroutine exactly once
|
||||||
if fingStatus.Load() == fingUninitialized && fingStatus.CompareAndSwap(fingUninitialized, fingCreated) {
|
if fingStatus.Load() == fingUninitialized && fingStatus.CompareAndSwap(fingUninitialized, fingCreated) {
|
||||||
go runfinq()
|
go runFinalizersAndCleanups()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +177,7 @@ func finalizercommit(gp *g, lock unsafe.Pointer) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the goroutine that runs all of the finalizers and cleanups.
|
// This is the goroutine that runs all of the finalizers and cleanups.
|
||||||
func runfinq() {
|
func runFinalizersAndCleanups() {
|
||||||
var (
|
var (
|
||||||
frame unsafe.Pointer
|
frame unsafe.Pointer
|
||||||
framecap uintptr
|
framecap uintptr
|
||||||
@ -243,7 +243,7 @@ func runfinq() {
|
|||||||
// cleanups also have a nil fint. Cleanups should have been processed before
|
// cleanups also have a nil fint. Cleanups should have been processed before
|
||||||
// reaching this point.
|
// reaching this point.
|
||||||
if f.fint == nil {
|
if f.fint == nil {
|
||||||
throw("missing type in runfinq")
|
throw("missing type in finalizer")
|
||||||
}
|
}
|
||||||
r := frame
|
r := frame
|
||||||
if argRegs > 0 {
|
if argRegs > 0 {
|
||||||
@ -270,7 +270,7 @@ func runfinq() {
|
|||||||
(*iface)(r).tab = assertE2I(ityp, (*eface)(r)._type)
|
(*iface)(r).tab = assertE2I(ityp, (*eface)(r)._type)
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
throw("bad kind in runfinq")
|
throw("bad type kind in finalizer")
|
||||||
}
|
}
|
||||||
fingStatus.Or(fingRunningFinalizer)
|
fingStatus.Or(fingRunningFinalizer)
|
||||||
reflectcall(nil, unsafe.Pointer(f.fn), frame, uint32(framesz), uint32(framesz), uint32(framesz), ®s)
|
reflectcall(nil, unsafe.Pointer(f.fn), frame, uint32(framesz), uint32(framesz), uint32(framesz), ®s)
|
||||||
|
@ -1578,7 +1578,7 @@ func TestGoroutineProfileConcurrency(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
includesFinalizer := func(s string) bool {
|
includesFinalizer := func(s string) bool {
|
||||||
return strings.Contains(s, "runtime.runfinq")
|
return strings.Contains(s, "runtime.runFinalizersAndCleanups")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Concurrent calls to the goroutine profiler should not trigger data races
|
// Concurrent calls to the goroutine profiler should not trigger data races
|
||||||
@ -2065,7 +2065,7 @@ func TestLabelSystemstack(t *testing.T) {
|
|||||||
// which part of the function they are
|
// which part of the function they are
|
||||||
// at.
|
// at.
|
||||||
mayBeLabeled = true
|
mayBeLabeled = true
|
||||||
case "runtime.bgsweep", "runtime.bgscavenge", "runtime.forcegchelper", "runtime.gcBgMarkWorker", "runtime.runfinq", "runtime.sysmon":
|
case "runtime.bgsweep", "runtime.bgscavenge", "runtime.forcegchelper", "runtime.gcBgMarkWorker", "runtime.runFinalizersAndCleanups", "runtime.sysmon":
|
||||||
// Runtime system goroutines or threads
|
// Runtime system goroutines or threads
|
||||||
// (such as those identified by
|
// (such as those identified by
|
||||||
// runtime.isSystemGoroutine). These
|
// runtime.isSystemGoroutine). These
|
||||||
|
@ -1131,8 +1131,9 @@ func showfuncinfo(sf srcFunc, firstFrame bool, calleeID abi.FuncID) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always show runtime.runfinq as context that this goroutine is
|
// Always show runtime.runFinalizersAndCleanups as context that this
|
||||||
// running finalizers, otherwise there is no obvious indicator.
|
// goroutine is running finalizers, otherwise there is no obvious
|
||||||
|
// indicator.
|
||||||
//
|
//
|
||||||
// TODO(prattmic): A more general approach would be to always show the
|
// TODO(prattmic): A more general approach would be to always show the
|
||||||
// outermost frame (besides runtime.goexit), even if it is a runtime.
|
// outermost frame (besides runtime.goexit), even if it is a runtime.
|
||||||
@ -1142,7 +1143,7 @@ func showfuncinfo(sf srcFunc, firstFrame bool, calleeID abi.FuncID) bool {
|
|||||||
// Unfortunately, implementing this requires looking ahead at the next
|
// Unfortunately, implementing this requires looking ahead at the next
|
||||||
// frame, which goes against traceback's incremental approach (see big
|
// frame, which goes against traceback's incremental approach (see big
|
||||||
// coment in traceback1).
|
// coment in traceback1).
|
||||||
if sf.funcID == abi.FuncID_runfinq {
|
if sf.funcID == abi.FuncID_runFinalizersAndCleanups {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1346,7 +1347,8 @@ func tracebackHexdump(stk stack, frame *stkframe, bad uintptr) {
|
|||||||
// isSystemGoroutine reports whether the goroutine g must be omitted
|
// isSystemGoroutine reports whether the goroutine g must be omitted
|
||||||
// in stack dumps and deadlock detector. This is any goroutine that
|
// in stack dumps and deadlock detector. This is any goroutine that
|
||||||
// starts at a runtime.* entry point, except for runtime.main,
|
// starts at a runtime.* entry point, except for runtime.main,
|
||||||
// runtime.handleAsyncEvent (wasm only) and sometimes runtime.runfinq.
|
// runtime.handleAsyncEvent (wasm only) and sometimes
|
||||||
|
// runtime.runFinalizersAndCleanups.
|
||||||
//
|
//
|
||||||
// If fixed is true, any goroutine that can vary between user and
|
// If fixed is true, any goroutine that can vary between user and
|
||||||
// system (that is, the finalizer goroutine) is considered a user
|
// system (that is, the finalizer goroutine) is considered a user
|
||||||
@ -1360,7 +1362,7 @@ func isSystemGoroutine(gp *g, fixed bool) bool {
|
|||||||
if f.funcID == abi.FuncID_runtime_main || f.funcID == abi.FuncID_corostart || f.funcID == abi.FuncID_handleAsyncEvent {
|
if f.funcID == abi.FuncID_runtime_main || f.funcID == abi.FuncID_corostart || f.funcID == abi.FuncID_handleAsyncEvent {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if f.funcID == abi.FuncID_runfinq {
|
if f.funcID == abi.FuncID_runFinalizersAndCleanups {
|
||||||
// We include the finalizer goroutine if it's calling
|
// We include the finalizer goroutine if it's calling
|
||||||
// back into user code.
|
// back into user code.
|
||||||
if fixed {
|
if fixed {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user