Source file src/runtime/debug/stack.go
1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package debug contains facilities for programs to debug themselves while 6 // they are running. 7 package debug 8 9 import ( 10 "internal/poll" 11 "os" 12 "runtime" 13 _ "unsafe" // for linkname 14 ) 15 16 // PrintStack prints to standard error the stack trace returned by runtime.Stack. 17 func PrintStack() { 18 os.Stderr.Write(Stack()) 19 } 20 21 // Stack returns a formatted stack trace of the goroutine that calls it. 22 // It calls [runtime.Stack] with a large enough buffer to capture the entire trace. 23 func Stack() []byte { 24 buf := make([]byte, 1024) 25 for { 26 n := runtime.Stack(buf, false) 27 if n < len(buf) { 28 return buf[:n] 29 } 30 buf = make([]byte, 2*len(buf)) 31 } 32 } 33 34 // CrashOptions provides options that control the formatting of the 35 // fatal crash message. 36 type CrashOptions struct { 37 /* for future expansion */ 38 } 39 40 // SetCrashOutput configures a single additional file where unhandled 41 // panics and other fatal errors are printed, in addition to standard error. 42 // There is only one additional file: calling SetCrashOutput again overrides 43 // any earlier call. 44 // SetCrashOutput duplicates f's file descriptor, so the caller may safely 45 // close f as soon as SetCrashOutput returns. 46 // To disable this additional crash output, call SetCrashOutput(nil). 47 // If called concurrently with a crash, some in-progress output may be written 48 // to the old file even after an overriding SetCrashOutput returns. 49 func SetCrashOutput(f *os.File, opts CrashOptions) error { 50 fd := ^uintptr(0) 51 if f != nil { 52 // The runtime will write to this file descriptor from 53 // low-level routines during a panic, possibly without 54 // a G, so we must call f.Fd() eagerly. This creates a 55 // danger that that the file descriptor is no longer 56 // valid at the time of the write, because the caller 57 // (incorrectly) called f.Close() and the kernel 58 // reissued the fd in a later call to open(2), leading 59 // to crashes being written to the wrong file. 60 // 61 // So, we duplicate the fd to obtain a private one 62 // that cannot be closed by the user. 63 // This also alleviates us from concerns about the 64 // lifetime and finalization of f. 65 // (DupCloseOnExec returns an fd, not a *File, so 66 // there is no finalizer, and we are responsible for 67 // closing it.) 68 // 69 // The new fd must be close-on-exec, otherwise if the 70 // crash monitor is a child process, it may inherit 71 // it, so it will never see EOF from the pipe even 72 // when this process crashes. 73 // 74 // A side effect of Fd() is that it calls SetBlocking, 75 // which is important so that writes of a crash report 76 // to a full pipe buffer don't get lost. 77 fd2, _, err := poll.DupCloseOnExec(int(f.Fd())) 78 if err != nil { 79 return err 80 } 81 runtime.KeepAlive(f) // prevent finalization before dup 82 fd = uintptr(fd2) 83 } 84 if prev := runtime_setCrashFD(fd); prev != ^uintptr(0) { 85 // We use NewFile+Close because it is portable 86 // unlike syscall.Close, whose parameter type varies. 87 os.NewFile(prev, "").Close() // ignore error 88 } 89 return nil 90 } 91 92 //go:linkname runtime_setCrashFD runtime.setCrashFD 93 func runtime_setCrashFD(uintptr) uintptr 94