Skip to content

Conversation

@timraymond
Copy link
Member

Reason for Change:

In the log.(*Logger).Init method, several different strategies are
considered based on the configuration provided by the user. In one
common case, a rotating log file is opened and the log output is tee-ed
into it. If there is any issue with opening that log file, the
log.(*Log).SetOutput method is never invoked on the underlying logger.
Since this standard library logger was created with nil passed as the
io.Writer, this results in a nil pointer deref panic. The error
causing the issue is also not surfaced to the user.

This initializes the standard library logger with the io.Discard
writer. This adheres to the original intention here, while also being a
safer alternative to nil (effectively writes are to /dev/null). Also,
the error is written out to stderr, in the hopes that an operator will
be able to diagnose and fix the issue (in the absense of a correct
logger configuration).

Finally, the logger initialization has been moved to a new
function, log.NewLoggerE that properly exposes the underlying error.
The original function, NewLogger, has been modified to use this
function instead and has been marked Deprecated.

Issue Fixed:
Fixes #1227

Requirements:

@ghost
Copy link

ghost commented Feb 8, 2022

CLA assistant check
All CLA requirements met.


// confirm the assumptions of this test before we run it:
if _, err := os.Stat(fullLogPath); err == nil {
t.Skipf("The log file at %q exists, so this test cannot sensibly run. Delete it first", fullLogPath)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would it be better to use a relative path and always delete it during test setup?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rbtr I like the general idea. I did a bit more research and found this SO post. The Go equivalent is os.TempDir which also does the right thing on Linux and Windows, so I'm inclined to use it. Patch forthcoming :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1 on os.TempDir

In the log.(*Logger).Init method, several different strategies are
considered based on the configuration provided by the user. In one
common case, a rotating log file is opened and the log output is tee-ed
into it. If there is any issue with opening that log file, the
`log.(*Log).SetOutput` method is never invoked on the underlying logger.
Since this standard library logger was created with `nil` passed as the
`io.Writer`, this results in a nil pointer deref panic. The error
causing the issue is also not surfaced to the user.

This initializes the standard library logger with the `io.Discard`
writer. This adheres to the original intention here, while also being a
safer alternative to nil (effectively writes are to /dev/null). Also,
the error is written out to stderr, in the hopes that an operator will
be able to diagnose and fix the issue (in the absense of a correct
logger configuration).

Finally, the logger initialization has been moved to a new
function, `log.NewLoggerE` that properly exposes the underlying error.
The original function, `NewLogger`, has been modified to use this
function instead and has been marked Deprecated.
@rbtr
Copy link
Collaborator

rbtr commented Feb 8, 2022

/azp run

The linter correctly pointed out that the types are redundant here.
While ordinarily I tend to leave them if the ellision appears in the
middle of the signature, I respect the linter's decision :)
@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Rather than trying to pull a non-existant path out of thin air and
hoping that it doesn't exist, this instead uses os.TempDir to create a
guaranteed-empty directory. From within the newly-created tempdir we try
to use a non-existent path. This is better both on a single platform,
but also has the benefit of working well on Windows too.
Copy link
Collaborator

@rbtr rbtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

deleting the wrong thing in the test, i think

Copy link
Collaborator

@rbtr rbtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forgot to include the comment 🙃

The intention of this test was to create a new temporary directory
rather than use the system's temporary directory. This mistake was
pointed out by @rbtr in a code review (thanks!).
When an error is present, we want to return both the error and the
logger to guarantee that a usable logger is always present. This returns
the logger in all circumstances and documents that fact in the godoc for
this function.
@timraymond
Copy link
Member Author

/azp run

@azure-pipelines
Copy link

Commenter does not have sufficient privileges for PR 1228 in repo Azure/azure-container-networking

@rbtr
Copy link
Collaborator

rbtr commented Feb 8, 2022

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

Copy link
Collaborator

@rbtr rbtr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@timraymond timraymond merged commit 297a157 into Azure:master Feb 10, 2022
@timraymond timraymond deleted the bugfix/log-panic branch February 10, 2022 21:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Creating a new logger on Linux without write permissions to /var causes panic

3 participants