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  

View as plain text