|
|
@@ -703,7 +703,16 @@ func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoTo
|
|
|
}
|
|
|
}
|
|
|
if s == fatalLog {
|
|
|
- // Make sure we see the trace for the current goroutine on standard error.
|
|
|
+ // If we got here via Exit rather than Fatal, print no stacks.
|
|
|
+ if atomic.LoadUint32(&fatalNoStacks) > 0 {
|
|
|
+ l.mu.Unlock()
|
|
|
+ timeoutFlush(10 * time.Second)
|
|
|
+ os.Exit(1)
|
|
|
+ }
|
|
|
+ // Dump all goroutine stacks before exiting.
|
|
|
+ // First, make sure we see the trace for the current goroutine on standard error.
|
|
|
+ // If -logtostderr has been specified, the loop below will do that anyway
|
|
|
+ // as the first stack in the full dump.
|
|
|
if !l.toStderr {
|
|
|
os.Stderr.Write(stacks(false))
|
|
|
}
|
|
|
@@ -1135,3 +1144,34 @@ func Fatalln(args ...interface{}) {
|
|
|
func Fatalf(format string, args ...interface{}) {
|
|
|
logging.printf(fatalLog, format, args...)
|
|
|
}
|
|
|
+
|
|
|
+// fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks.
|
|
|
+// It allows Exit and relatives to use the Fatal logs.
|
|
|
+var fatalNoStacks uint32
|
|
|
+
|
|
|
+// Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
|
|
|
+// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
|
|
|
+func Exit(args ...interface{}) {
|
|
|
+ atomic.StoreUint32(&fatalNoStacks, 1)
|
|
|
+ logging.print(fatalLog, args...)
|
|
|
+}
|
|
|
+
|
|
|
+// ExitDepth acts as Exit but uses depth to determine which call frame to log.
|
|
|
+// ExitDepth(0, "msg") is the same as Exit("msg").
|
|
|
+func ExitDepth(depth int, args ...interface{}) {
|
|
|
+ atomic.StoreUint32(&fatalNoStacks, 1)
|
|
|
+ logging.printDepth(fatalLog, depth, args...)
|
|
|
+}
|
|
|
+
|
|
|
+// Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
|
|
|
+func Exitln(args ...interface{}) {
|
|
|
+ atomic.StoreUint32(&fatalNoStacks, 1)
|
|
|
+ logging.println(fatalLog, args...)
|
|
|
+}
|
|
|
+
|
|
|
+// Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1).
|
|
|
+// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
|
|
|
+func Exitf(format string, args ...interface{}) {
|
|
|
+ atomic.StoreUint32(&fatalNoStacks, 1)
|
|
|
+ logging.printf(fatalLog, format, args...)
|
|
|
+}
|