aboutsummaryrefslogtreecommitdiff
path: root/src/runtime/panic.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/panic.go')
-rw-r--r--src/runtime/panic.go39
1 files changed, 32 insertions, 7 deletions
diff --git a/src/runtime/panic.go b/src/runtime/panic.go
index e4cc7bfb31..2e6f7af2ce 100644
--- a/src/runtime/panic.go
+++ b/src/runtime/panic.go
@@ -986,6 +986,15 @@ func sync_throw(s string) {
throw(s)
}
+//go:linkname sync_fatal sync.fatal
+func sync_fatal(s string) {
+ fatal(s)
+}
+
+// throw triggers a fatal error that dumps a stack trace and exits.
+//
+// throw should be used for runtime-internal fatal errors where Go itself,
+// rather than user code, may be at fault for the failure.
//go:nosplit
func throw(s string) {
// Everything throw does should be recursively nosplit so it
@@ -993,12 +1002,23 @@ func throw(s string) {
systemstack(func() {
print("fatal error: ", s, "\n")
})
- gp := getg()
- if gp.m.throwing == 0 {
- gp.m.throwing = 1
- }
+
+ fatalthrow()
+}
+
+// fatal triggers a fatal error that dumps a stack trace and exits.
+//
+// fatal is equivalent to throw, but is used when user code is expected to be
+// at fault for the failure, such as racing map writes.
+//go:nosplit
+func fatal(s string) {
+ // Everything fatal does should be recursively nosplit so it
+ // can be called even when it's unsafe to grow the stack.
+ systemstack(func() {
+ print("fatal error: ", s, "\n")
+ })
+
fatalthrow()
- *(*int)(nil) = 0 // not reached
}
// runningPanicDefers is non-zero while running deferred functions for panic.
@@ -1047,8 +1067,13 @@ func fatalthrow() {
pc := getcallerpc()
sp := getcallersp()
gp := getg()
- // Switch to the system stack to avoid any stack growth, which
- // may make things worse if the runtime is in a bad state.
+
+ if gp.m.throwing == 0 {
+ gp.m.throwing = 1
+ }
+
+ // Switch to the system stack to avoid any stack growth, which may make
+ // things worse if the runtime is in a bad state.
systemstack(func() {
startpanic_m()