Files
moby/daemon/internal/stack/stackdump.go
T
Paweł Gronowski 88df5b627e daemon: Adjust file permissions for umask 000
Clearing the daemon umask means creation sites can no longer rely on
umask 0022 to remove group/other-write bits from permissive modes.

Adjust modes for daemon-owned files that previously depended on the old
umask:

- fuse-overlayfs lower file
- goroutine stack dump file
- layer migration tar-data file
- network namespace mount file

Signed-off-by: Paweł Gronowski <pawel.gronowski@docker.com>
2026-06-17 14:57:17 +02:00

60 lines
1.3 KiB
Go

package stack
import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/pkg/errors"
)
const stacksLogNameTemplate = "goroutine-stacks-%s.log"
// Dump outputs the runtime stack to os.StdErr.
func Dump() {
_ = dump(os.Stderr)
}
// DumpToFile appends the runtime stack into a file named "goroutine-stacks-<timestamp>.log"
// in dir and returns the full path to that file. If no directory name is
// provided, it outputs to os.Stderr.
func DumpToFile(dir string) (string, error) {
var f *os.File
if dir != "" {
path := filepath.Join(dir, fmt.Sprintf(stacksLogNameTemplate, strings.ReplaceAll(time.Now().Format(time.RFC3339), ":", "")))
var err error
f, err = os.OpenFile(path, os.O_CREATE|os.O_WRONLY, 0o644)
if err != nil {
return "", errors.Wrap(err, "failed to open file to write the goroutine stacks")
}
defer func() {
_ = f.Sync()
_ = f.Close()
}()
} else {
f = os.Stderr
}
return f.Name(), dump(f)
}
func dump(f *os.File) error {
var (
buf []byte
stackSize int
)
bufferLen := 16384
for stackSize == len(buf) {
buf = make([]byte, bufferLen)
stackSize = runtime.Stack(buf, true)
bufferLen *= 2
}
buf = buf[:stackSize]
if _, err := f.Write(buf); err != nil {
return errors.Wrap(err, "failed to write goroutine stacks")
}
return nil
}