Don't print errors twice

Function fatal() and method (*FatalWriter).Write log the error to the
logger when prints it to stderr just be be sure. Since by default the
logger is configured to write to os.Stderr, we get something like this
as a result:

> # ./runc checkpoint xx5
> ERRO[0000] Container cannot be checkpointed in stopped state
> Container cannot be checkpointed in stopped state

or

> # ./runc sdf
> ERRO[0000] No help topic for 'sdf'
> No help topic for 'sdf'

This is very annoying.

To fix, check if logrus is logging into stderr, and if it is, skip
the second write.

After this commit:

> # ./runc sdf
> ERRO[0000] No help topic for 'sdf'

> [root@kir-rhat runc]# ./runc --log=out sdf
> No help topic for 'sdf'

Note that now the logrus prefix might be in or out, depending on whether
logrus is logging to stderr or not. This is not perfect, but better than
the old behavior.

Signed-off-by: Kir Kolyshkin <kolyshkin@gmail.com>
This commit is contained in:
Kir Kolyshkin 2020-05-02 16:19:25 -07:00
parent c52a598d74
commit 1b84a21c51
2 changed files with 13 additions and 2 deletions

View File

@ -159,7 +159,10 @@ type FatalWriter struct {
func (f *FatalWriter) Write(p []byte) (n int, err error) {
logrus.Error(string(p))
return f.cliErrWriter.Write(p)
if !logrusToStderr() {
return f.cliErrWriter.Write(p)
}
return len(p), nil
}
func createLogConfig(context *cli.Context) logs.Config {

View File

@ -45,12 +45,20 @@ func checkArgs(context *cli.Context, expected, checkType int) error {
return nil
}
func logrusToStderr() bool {
l, ok := logrus.StandardLogger().Out.(*os.File)
return ok && l.Fd() == os.Stderr.Fd()
}
// fatal prints the error's details if it is a libcontainer specific error type
// then exits the program with an exit status of 1.
func fatal(err error) {
// make sure the error is written to the logger
logrus.Error(err)
fmt.Fprintln(os.Stderr, err)
if !logrusToStderr() {
fmt.Fprintln(os.Stderr, err)
}
os.Exit(1)
}