mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Allow to specify a separate log for GO's runtime messages
GO's runtime calls the write system call twice to print "panic:" and "the reason of this panic", so here is a race window when other threads can print something to the log and we will see something like this: panic: log messages from another thread The reason of the panic. This confuses the syzkaller blacklist and dedup detection. It also makes the logs generally difficult to read. e.g., data races often have one side of the race, followed by a large "diagnosis" dump, finally followed by the other side of the race. PiperOrigin-RevId: 297887895
This commit is contained in:
@@ -158,6 +158,9 @@ type Config struct {
|
||||
// DebugLog is the path to log debug information to, if not empty.
|
||||
DebugLog string
|
||||
|
||||
// PanicLog is the path to log GO's runtime messages, if not empty.
|
||||
PanicLog string
|
||||
|
||||
// DebugLogFormat is the log format for debug.
|
||||
DebugLogFormat string
|
||||
|
||||
@@ -269,6 +272,7 @@ func (c *Config) ToFlags() []string {
|
||||
"--log=" + c.LogFilename,
|
||||
"--log-format=" + c.LogFormat,
|
||||
"--debug-log=" + c.DebugLog,
|
||||
"--panic-log=" + c.PanicLog,
|
||||
"--debug-log-format=" + c.DebugLogFormat,
|
||||
"--file-access=" + c.FileAccess.String(),
|
||||
"--overlay=" + strconv.FormatBool(c.Overlay),
|
||||
|
||||
+23
-14
@@ -54,9 +54,11 @@ var (
|
||||
|
||||
// Debugging flags.
|
||||
debugLog = flag.String("debug-log", "", "additional location for logs. If it ends with '/', log files are created inside the directory with default names. The following variables are available: %TIMESTAMP%, %COMMAND%.")
|
||||
panicLog = flag.String("panic-log", "", "file path were panic reports and other Go's runtime messages are written.")
|
||||
logPackets = flag.Bool("log-packets", false, "enable network packet logging.")
|
||||
logFD = flag.Int("log-fd", -1, "file descriptor to log to. If set, the 'log' flag is ignored.")
|
||||
debugLogFD = flag.Int("debug-log-fd", -1, "file descriptor to write debug logs to. If set, the 'debug-log-dir' flag is ignored.")
|
||||
panicLogFD = flag.Int("panic-log-fd", -1, "file descriptor to write Go's runtime messages.")
|
||||
debugLogFormat = flag.String("debug-log-format", "text", "log format: text (default), json, or json-k8s.")
|
||||
alsoLogToStderr = flag.Bool("alsologtostderr", false, "send log messages to stderr.")
|
||||
|
||||
@@ -206,6 +208,7 @@ func main() {
|
||||
LogFilename: *logFilename,
|
||||
LogFormat: *logFormat,
|
||||
DebugLog: *debugLog,
|
||||
PanicLog: *panicLog,
|
||||
DebugLogFormat: *debugLogFormat,
|
||||
FileAccess: fsAccess,
|
||||
FSGoferHostUDS: *fsGoferHostUDS,
|
||||
@@ -258,20 +261,6 @@ func main() {
|
||||
if *debugLogFD > -1 {
|
||||
f := os.NewFile(uintptr(*debugLogFD), "debug log file")
|
||||
|
||||
// Quick sanity check to make sure no other commands get passed
|
||||
// a log fd (they should use log dir instead).
|
||||
if subcommand != "boot" && subcommand != "gofer" {
|
||||
cmd.Fatalf("flag --debug-log-fd should only be passed to 'boot' and 'gofer' command, but was passed to %q", subcommand)
|
||||
}
|
||||
|
||||
// If we are the boot process, then we own our stdio FDs and can do what we
|
||||
// want with them. Since Docker and Containerd both eat boot's stderr, we
|
||||
// dup our stderr to the provided log FD so that panics will appear in the
|
||||
// logs, rather than just disappear.
|
||||
if err := syscall.Dup3(int(f.Fd()), int(os.Stderr.Fd()), 0); err != nil {
|
||||
cmd.Fatalf("error dup'ing fd %d to stderr: %v", f.Fd(), err)
|
||||
}
|
||||
|
||||
e = newEmitter(*debugLogFormat, f)
|
||||
|
||||
} else if *debugLog != "" {
|
||||
@@ -287,6 +276,26 @@ func main() {
|
||||
e = newEmitter("text", ioutil.Discard)
|
||||
}
|
||||
|
||||
if *panicLogFD > -1 || *debugLogFD > -1 {
|
||||
fd := *panicLogFD
|
||||
if fd < 0 {
|
||||
fd = *debugLogFD
|
||||
}
|
||||
// Quick sanity check to make sure no other commands get passed
|
||||
// a log fd (they should use log dir instead).
|
||||
if subcommand != "boot" && subcommand != "gofer" {
|
||||
cmd.Fatalf("flags --debug-log-fd and --panic-log-fd should only be passed to 'boot' and 'gofer' command, but was passed to %q", subcommand)
|
||||
}
|
||||
|
||||
// If we are the boot process, then we own our stdio FDs and can do what we
|
||||
// want with them. Since Docker and Containerd both eat boot's stderr, we
|
||||
// dup our stderr to the provided log FD so that panics will appear in the
|
||||
// logs, rather than just disappear.
|
||||
if err := syscall.Dup3(fd, int(os.Stderr.Fd()), 0); err != nil {
|
||||
cmd.Fatalf("error dup'ing fd %d to stderr: %v", fd, err)
|
||||
}
|
||||
}
|
||||
|
||||
if *alsoLogToStderr {
|
||||
e = &log.MultiEmitter{e, newEmitter(*debugLogFormat, os.Stderr)}
|
||||
}
|
||||
|
||||
@@ -369,6 +369,24 @@ func (s *Sandbox) createSandboxProcess(conf *boot.Config, args *Args, startSyncF
|
||||
cmd.Args = append(cmd.Args, "--debug-log-fd="+strconv.Itoa(nextFD))
|
||||
nextFD++
|
||||
}
|
||||
if conf.PanicLog != "" {
|
||||
test := ""
|
||||
if len(conf.TestOnlyTestNameEnv) != 0 {
|
||||
// Fetch test name if one is provided and the test only flag was set.
|
||||
if t, ok := specutils.EnvVar(args.Spec.Process.Env, conf.TestOnlyTestNameEnv); ok {
|
||||
test = t
|
||||
}
|
||||
}
|
||||
|
||||
panicLogFile, err := specutils.DebugLogFile(conf.PanicLog, "panic", test)
|
||||
if err != nil {
|
||||
return fmt.Errorf("opening debug log file in %q: %v", conf.PanicLog, err)
|
||||
}
|
||||
defer panicLogFile.Close()
|
||||
cmd.ExtraFiles = append(cmd.ExtraFiles, panicLogFile)
|
||||
cmd.Args = append(cmd.Args, "--panic-log-fd="+strconv.Itoa(nextFD))
|
||||
nextFD++
|
||||
}
|
||||
|
||||
cmd.Args = append(cmd.Args, "--panic-signal="+strconv.Itoa(int(syscall.SIGTERM)))
|
||||
|
||||
|
||||
Reference in New Issue
Block a user