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.
7package debug
8
9import (
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.
17func 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.
23func 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.
36type 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.
49func 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
93func runtime_setCrashFD(uintptr) uintptr
94