mirror of
https://github.com/golang/go
synced 2024-11-20 08:04:42 -07:00
c3b5db895b
In Go 1.3 the runtime called panicstring to report errors like divide by zero or memory faults. Now we call panic (gopanic) with pre-allocated error values. That new path is missing the checking that panicstring did, so add it there. The only call to panicstring left is in cnew, which is problematic because if it fails, probably the heap is corrupt. In that case, calling panicstring creates a new errorCString (no allocation there), but then panic tries to print it, invoking errorCString.Error, which does a string concatenation (allocating), which then dies. Replace that one panicstring with a throw: cnew is for allocating runtime data structures and should never ask for an inappropriate amount of memory. With panicstring gone, delete newErrorCString, errorCString. While we're here, delete newErrorString, not called by anyone. (It can't be: that would be C code calling Go code that might block or grow the stack.) Found while debugging a malloc corruption. This resulted in 'panic during panic' instead of a more useful message. LGTM=khr R=khr CC=golang-codereviews https://golang.org/cl/138290045
108 lines
2.5 KiB
Go
108 lines
2.5 KiB
Go
// Copyright 2010 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
|
|
|
|
import "unsafe"
|
|
|
|
// The Error interface identifies a run time error.
|
|
type Error interface {
|
|
error
|
|
|
|
// RuntimeError is a no-op function but
|
|
// serves to distinguish types that are runtime
|
|
// errors from ordinary errors: a type is a
|
|
// runtime error if it has a RuntimeError method.
|
|
RuntimeError()
|
|
}
|
|
|
|
// A TypeAssertionError explains a failed type assertion.
|
|
type TypeAssertionError struct {
|
|
interfaceString string
|
|
concreteString string
|
|
assertedString string
|
|
missingMethod string // one method needed by Interface, missing from Concrete
|
|
}
|
|
|
|
func (*TypeAssertionError) RuntimeError() {}
|
|
|
|
func (e *TypeAssertionError) Error() string {
|
|
inter := e.interfaceString
|
|
if inter == "" {
|
|
inter = "interface"
|
|
}
|
|
if e.concreteString == "" {
|
|
return "interface conversion: " + inter + " is nil, not " + e.assertedString
|
|
}
|
|
if e.missingMethod == "" {
|
|
return "interface conversion: " + inter + " is " + e.concreteString +
|
|
", not " + e.assertedString
|
|
}
|
|
return "interface conversion: " + e.concreteString + " is not " + e.assertedString +
|
|
": missing method " + e.missingMethod
|
|
}
|
|
|
|
// For calling from C.
|
|
func newTypeAssertionError(ps1, ps2, ps3 *string, pmeth *string, ret *interface{}) {
|
|
var s1, s2, s3, meth string
|
|
|
|
if ps1 != nil {
|
|
s1 = *ps1
|
|
}
|
|
if ps2 != nil {
|
|
s2 = *ps2
|
|
}
|
|
if ps3 != nil {
|
|
s3 = *ps3
|
|
}
|
|
if pmeth != nil {
|
|
meth = *pmeth
|
|
}
|
|
*ret = &TypeAssertionError{s1, s2, s3, meth}
|
|
}
|
|
|
|
// An errorString represents a runtime error described by a single string.
|
|
type errorString string
|
|
|
|
func (e errorString) RuntimeError() {}
|
|
|
|
func (e errorString) Error() string {
|
|
return "runtime error: " + string(e)
|
|
}
|
|
|
|
type stringer interface {
|
|
String() string
|
|
}
|
|
|
|
func typestring(x interface{}) string {
|
|
e := (*eface)(unsafe.Pointer(&x))
|
|
return *e._type._string
|
|
}
|
|
|
|
// For calling from C.
|
|
// Prints an argument passed to panic.
|
|
// There's room for arbitrary complexity here, but we keep it
|
|
// simple and handle just a few important cases: int, string, and Stringer.
|
|
func printany(i interface{}) {
|
|
switch v := i.(type) {
|
|
case nil:
|
|
print("nil")
|
|
case stringer:
|
|
print(v.String())
|
|
case error:
|
|
print(v.Error())
|
|
case int:
|
|
print(v)
|
|
case string:
|
|
print(v)
|
|
default:
|
|
print("(", typestring(i), ") ", i)
|
|
}
|
|
}
|
|
|
|
// called from generated code
|
|
func panicwrap(pkg, typ, meth string) {
|
|
panic("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")
|
|
}
|