mirror of
https://github.com/golang/go
synced 2024-11-18 22:04:43 -07:00
runtime: make execution error panic values implement the Error interface
Make execution panics implement Error as mandated by https://golang.org/ref/spec#Run_time_panics, instead of panics with strings. Fixes #14965 Change-Id: I7827f898b9b9c08af541db922cc24fa0800ff18a Reviewed-on: https://go-review.googlesource.com/21214 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
824d8c10fe
commit
e4f1d9cf2e
@ -64,7 +64,7 @@ func makechan(t *chantype, size int64) *hchan {
|
||||
throw("makechan: bad alignment")
|
||||
}
|
||||
if size < 0 || int64(uintptr(size)) != size || (elem.size > 0 && uintptr(size) > (_MaxMem-hchanSize)/elem.size) {
|
||||
panic("makechan: size out of range")
|
||||
panic(plainError("makechan: size out of range"))
|
||||
}
|
||||
|
||||
var c *hchan
|
||||
@ -171,7 +171,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
||||
|
||||
if c.closed != 0 {
|
||||
unlock(&c.lock)
|
||||
panic("send on closed channel")
|
||||
panic(plainError("send on closed channel"))
|
||||
}
|
||||
|
||||
if sg := c.recvq.dequeue(); sg != nil {
|
||||
@ -231,7 +231,7 @@ func chansend(t *chantype, c *hchan, ep unsafe.Pointer, block bool, callerpc uin
|
||||
if c.closed == 0 {
|
||||
throw("chansend: spurious wakeup")
|
||||
}
|
||||
panic("send on closed channel")
|
||||
panic(plainError("send on closed channel"))
|
||||
}
|
||||
gp.param = nil
|
||||
if mysg.releasetime > 0 {
|
||||
@ -302,13 +302,13 @@ func sendDirect(t *_type, sg *sudog, src unsafe.Pointer) {
|
||||
|
||||
func closechan(c *hchan) {
|
||||
if c == nil {
|
||||
panic("close of nil channel")
|
||||
panic(plainError("close of nil channel"))
|
||||
}
|
||||
|
||||
lock(&c.lock)
|
||||
if c.closed != 0 {
|
||||
unlock(&c.lock)
|
||||
panic("close of closed channel")
|
||||
panic(plainError("close of closed channel"))
|
||||
}
|
||||
|
||||
if raceenabled {
|
||||
|
@ -273,6 +273,52 @@ func TestGoexitInPanic(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Issue 14965: Runtime panics should be of type runtime.Error
|
||||
func TestRuntimePanicWithRuntimeError(t *testing.T) {
|
||||
testCases := [...]func(){
|
||||
0: func() {
|
||||
var m map[uint64]bool
|
||||
m[1234] = true
|
||||
},
|
||||
1: func() {
|
||||
ch := make(chan struct{})
|
||||
close(ch)
|
||||
close(ch)
|
||||
},
|
||||
2: func() {
|
||||
var ch = make(chan struct{})
|
||||
close(ch)
|
||||
ch <- struct{}{}
|
||||
},
|
||||
3: func() {
|
||||
var s = make([]int, 2)
|
||||
_ = s[2]
|
||||
},
|
||||
4: func() {
|
||||
n := -1
|
||||
_ = make(chan bool, n)
|
||||
},
|
||||
5: func() {
|
||||
close((chan bool)(nil))
|
||||
},
|
||||
}
|
||||
|
||||
for i, fn := range testCases {
|
||||
got := panicValue(fn)
|
||||
if _, ok := got.(runtime.Error); !ok {
|
||||
t.Errorf("test #%d: recovered value %v(type %T) does not implement runtime.Error", i, got, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func panicValue(fn func()) (recovered interface{}) {
|
||||
defer func() {
|
||||
recovered = recover()
|
||||
}()
|
||||
fn()
|
||||
return
|
||||
}
|
||||
|
||||
func TestPanicAfterGoexit(t *testing.T) {
|
||||
// an uncaught panic should still work after goexit
|
||||
output := runTestProg(t, "testprog", "PanicAfterGoexit")
|
||||
|
@ -50,6 +50,17 @@ func (e errorString) Error() string {
|
||||
return "runtime error: " + string(e)
|
||||
}
|
||||
|
||||
// plainError represents a runtime error described a string without
|
||||
// the prefix "runtime error: " after invoking errorString.Error().
|
||||
// See Issue #14965.
|
||||
type plainError string
|
||||
|
||||
func (e plainError) RuntimeError() {}
|
||||
|
||||
func (e plainError) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
type stringer interface {
|
||||
String() string
|
||||
}
|
||||
@ -82,5 +93,5 @@ func printany(i interface{}) {
|
||||
|
||||
// called from generated code
|
||||
func panicwrap(pkg, typ, meth string) {
|
||||
panic("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")
|
||||
panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer"))
|
||||
}
|
||||
|
@ -194,7 +194,7 @@ func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
|
||||
}
|
||||
|
||||
if hint < 0 || int64(int32(hint)) != hint {
|
||||
panic("makemap: size out of range")
|
||||
panic(plainError("makemap: size out of range"))
|
||||
// TODO: make hint an int, then none of this nonsense
|
||||
}
|
||||
|
||||
@ -428,7 +428,7 @@ func mapaccessK(t *maptype, h *hmap, key unsafe.Pointer) (unsafe.Pointer, unsafe
|
||||
|
||||
func mapassign1(t *maptype, h *hmap, key unsafe.Pointer, val unsafe.Pointer) {
|
||||
if h == nil {
|
||||
panic("assignment to entry in nil map")
|
||||
panic(plainError("assignment to entry in nil map"))
|
||||
}
|
||||
if raceenabled {
|
||||
callerpc := getcallerpc(unsafe.Pointer(&t))
|
||||
|
@ -793,7 +793,7 @@ func newarray(typ *_type, n uintptr) unsafe.Pointer {
|
||||
flags |= flagNoScan
|
||||
}
|
||||
if int(n) < 0 || (typ.size > 0 && n > _MaxMem/typ.size) {
|
||||
panic("runtime: allocation size out of range")
|
||||
panic(plainError("runtime: allocation size out of range"))
|
||||
}
|
||||
return mallocgc(typ.size*n, typ, flags)
|
||||
}
|
||||
|
@ -381,7 +381,7 @@ func badmcall2(fn func(*g)) {
|
||||
}
|
||||
|
||||
func badreflectcall() {
|
||||
panic("runtime: arg size to reflect.call more than 1GB")
|
||||
panic(plainError("arg size to reflect.call more than 1GB"))
|
||||
}
|
||||
|
||||
func lockedOSThread() bool {
|
||||
|
@ -594,7 +594,7 @@ retc:
|
||||
sclose:
|
||||
// send on closed channel
|
||||
selunlock(scases, lockorder)
|
||||
panic("send on closed channel")
|
||||
panic(plainError("send on closed channel"))
|
||||
}
|
||||
|
||||
func (c *hchan) sortkey() uintptr {
|
||||
|
Loading…
Reference in New Issue
Block a user