Commit 0c8f6cc0 authored by Ian Lance Taylor's avatar Ian Lance Taylor Committed by Brad Fitzpatrick

runtime: if InjectDebugCall sees "not at safe point", keep trying

Fixes #35376

Change-Id: Ib95ad336425e73cc4d412dafed0ba5e0a8130bd2
Reviewed-on: https://go-review.googlesource.com/c/go/+/205718
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarBryan C. Mills <bcmills@google.com>
parent 7714dcac
...@@ -126,7 +126,7 @@ func TestDebugCall(t *testing.T) { ...@@ -126,7 +126,7 @@ func TestDebugCall(t *testing.T) {
return x + 1 return x + 1
} }
args.x = 42 args.x = 42
if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill); err != nil { if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if args.yRet != 43 { if args.yRet != 43 {
...@@ -155,7 +155,7 @@ func TestDebugCallLarge(t *testing.T) { ...@@ -155,7 +155,7 @@ func TestDebugCallLarge(t *testing.T) {
args.in[i] = i args.in[i] = i
want[i] = i + 1 want[i] = i + 1
} }
if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill); err != nil { if _, err := runtime.InjectDebugCall(g, fn, &args, debugCallTKill, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if want != args.out { if want != args.out {
...@@ -168,7 +168,7 @@ func TestDebugCallGC(t *testing.T) { ...@@ -168,7 +168,7 @@ func TestDebugCallGC(t *testing.T) {
defer after() defer after()
// Inject a call that performs a GC. // Inject a call that performs a GC.
if _, err := runtime.InjectDebugCall(g, runtime.GC, nil, debugCallTKill); err != nil { if _, err := runtime.InjectDebugCall(g, runtime.GC, nil, debugCallTKill, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
...@@ -179,7 +179,7 @@ func TestDebugCallGrowStack(t *testing.T) { ...@@ -179,7 +179,7 @@ func TestDebugCallGrowStack(t *testing.T) {
// Inject a call that grows the stack. debugCallWorker checks // Inject a call that grows the stack. debugCallWorker checks
// for stack pointer breakage. // for stack pointer breakage.
if _, err := runtime.InjectDebugCall(g, func() { growStack(nil) }, nil, debugCallTKill); err != nil { if _, err := runtime.InjectDebugCall(g, func() { growStack(nil) }, nil, debugCallTKill, false); err != nil {
t.Fatal(err) t.Fatal(err)
} }
} }
...@@ -215,7 +215,7 @@ func TestDebugCallUnsafePoint(t *testing.T) { ...@@ -215,7 +215,7 @@ func TestDebugCallUnsafePoint(t *testing.T) {
runtime.Gosched() runtime.Gosched()
} }
_, err := runtime.InjectDebugCall(g, func() {}, nil, debugCallTKill) _, err := runtime.InjectDebugCall(g, func() {}, nil, debugCallTKill, true)
if msg := "call not at safe point"; err == nil || err.Error() != msg { if msg := "call not at safe point"; err == nil || err.Error() != msg {
t.Fatalf("want %q, got %s", msg, err) t.Fatalf("want %q, got %s", msg, err)
} }
...@@ -239,7 +239,7 @@ func TestDebugCallPanic(t *testing.T) { ...@@ -239,7 +239,7 @@ func TestDebugCallPanic(t *testing.T) {
}() }()
g := <-ready g := <-ready
p, err := runtime.InjectDebugCall(g, func() { panic("test") }, nil, debugCallTKill) p, err := runtime.InjectDebugCall(g, func() { panic("test") }, nil, debugCallTKill, false)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
......
...@@ -20,7 +20,7 @@ import ( ...@@ -20,7 +20,7 @@ import (
// //
// On success, InjectDebugCall returns the panic value of fn or nil. // On success, InjectDebugCall returns the panic value of fn or nil.
// If fn did not panic, its results will be available in args. // If fn did not panic, its results will be available in args.
func InjectDebugCall(gp *g, fn, args interface{}, tkill func(tid int) error) (interface{}, error) { func InjectDebugCall(gp *g, fn, args interface{}, tkill func(tid int) error, returnOnUnsafePoint bool) (interface{}, error) {
if gp.lockedm == 0 { if gp.lockedm == 0 {
return nil, plainError("goroutine not locked to thread") return nil, plainError("goroutine not locked to thread")
} }
...@@ -64,6 +64,12 @@ func InjectDebugCall(gp *g, fn, args interface{}, tkill func(tid int) error) (in ...@@ -64,6 +64,12 @@ func InjectDebugCall(gp *g, fn, args interface{}, tkill func(tid int) error) (in
notetsleepg(&h.done, -1) notetsleepg(&h.done, -1)
if h.err != "" { if h.err != "" {
switch h.err { switch h.err {
case "call not at safe point":
if returnOnUnsafePoint {
// This is for TestDebugCallUnsafePoint.
return nil, h.err
}
fallthrough
case "retry _Grunnable", "executing on Go runtime stack": case "retry _Grunnable", "executing on Go runtime stack":
// These are transient states. Try to get out of them. // These are transient states. Try to get out of them.
if i < 100 { if i < 100 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment