Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle errors on close in config file write. #2595

Merged
merged 1 commit into from
Jul 15, 2020

Conversation

cpuguy83
Copy link
Collaborator

@cpuguy83 cpuguy83 commented Jun 19, 2020

I'm not sure if this fixes anything, however I have seen some weird
behavior on Windows where temp config files are left around and there
doesn't seem to be any errors reported, and an empty config.json.

@cpuguy83 cpuguy83 force-pushed the handle_close_error_on_save branch 2 times, most recently from cb2ff4c to 6ac4868 Compare June 19, 2020 18:26
I'm not sure if this fixes anything, however I have seen some weird
behavior on Windows where temp config files are left around and there
doesn't seem to be any errors reported.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
@cpuguy83 cpuguy83 force-pushed the handle_close_error_on_save branch from 6ac4868 to d021730 Compare June 19, 2020 18:26
@codecov-commenter
Copy link

Codecov Report

Merging #2595 into master will decrease coverage by 0.00%.
The diff coverage is 37.50%.

@@            Coverage Diff             @@
##           master    #2595      +/-   ##
==========================================
- Coverage   58.05%   58.04%   -0.01%     
==========================================
  Files         295      295              
  Lines       21165    21170       +5     
==========================================
+ Hits        12288    12289       +1     
- Misses       7975     7977       +2     
- Partials      902      904       +2     

@cpuguy83
Copy link
Collaborator Author

The existence of https://success.docker.com/article/warning-error-loading-configjson seems to indicate there is a problem here 😂

@thaJeztah
Copy link
Member

thaJeztah commented Jun 22, 2020

The existence of https://success.docker.com/article/warning-error-loading-configjson seems to indicate there is a problem here 😂

That seems to be about loading the config file, not saving? Or is that hitting this code?

WARNING: Error loading config file:.docker\config.json - EOF

Also wondering if that's related to empty config files, and if we should ignore empty files (just like we ignore empty {} JSON) 🤔

Testing if we're still producing an error for empty files, and it looks like we do;

mkdir -p ~/.docker && touch ~/.docker/config.json

docker pull busybox
WARNING: Error loading config file: /root/.docker/config.json: EOF

temp.Close()
if retErr != nil {
if err := os.Remove(temp.Name()); err != nil {
logrus.WithError(err).WithField("file", temp.Name()).Debug("Error cleaning up temp file")
Copy link
Member

Choose a reason for hiding this comment

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

Given that in this case, we have exited early, and didn't update the actual ~/.docker/config.json, perhaps we should print this as a warning?

Something like

WARNING: Failed to update config file: error cleaning up temp file 

WDYT?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could, but we should already get an error returned.

@cpuguy83
Copy link
Collaborator Author

That seems to be about loading the config file, not saving? Or is that hitting this code?

Right but how did it get that way?

@cpuguy83
Copy link
Collaborator Author

The symptom I've seen is multiple temp files left behind and an empty config file, btw.

defer func() {
temp.Close()
if retErr != nil {
if err := os.Remove(temp.Name()); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Not sure if there's a situation where that's possible (thinking if an error occurs on os.Rename(); not sure how atomic that is); should we ignore errors if the file didn't exist?

Suggested change
if err := os.Remove(temp.Name()); err != nil {
if err := os.Remove(temp.Name()); err != nil && !os.IsNotExist(err) {

Guess it's not needed 😅

@thaJeztah
Copy link
Member

Should we consider using something like https://github.com/moby/moby/blob/4609153995b59f54b507446eb2b2cca9ebbbf8e8/pkg/ioutils/fswriters.go#L13 or https://github.com/google/renameio (which seems to handle specific corner-cases)?

Problem I see with that approach is that we would (at least not "out of the box") loose the copyFilePermissions() that would preserve ownership of the file.

Hm.. looks like we may need to have a look at that in general. Here's some fun thing I tried;

mkdir -p ~/.docker
touch ~/real-config.json
ln -s ~/real-config.json ~/.docker/config.json

ls -la ~/.docker/config.json
# lrwxrwxrwx 1 root root 22 Jun 23 12:34 /root/.docker/config.json -> /root/real-config.json

docker login
# Username: thajeztah
# Password:

# Login Succeeded

ls -la ~/.docker/config.json
-rw-r--r-- 1 root root 229 Jun 23 12:36 /root/.docker/config.json

Looks like we need to resolve symlinks before we rename. Something like;

cfgFile := configFile.Filename
if f, err := os.Readlink(cfgFile); err == nil {
	cfgFile = f
}
// Try copying the current config file (if any) ownership and permissions
copyFilePermissions(cfgFile, temp.Name())
return os.Rename(temp.Name(), cfgFile)

@thaJeztah
Copy link
Member

Opened #2599 for consideration (if we think it's ok to ignore an empty config file); #2595 (comment)

@cpuguy83
Copy link
Collaborator Author

Ping

Copy link
Member

@thaJeztah thaJeztah left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@silvin-lubecki silvin-lubecki left a comment

Choose a reason for hiding this comment

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

LGTM

@silvin-lubecki silvin-lubecki merged commit e4e754b into docker:master Jul 15, 2020
@cpuguy83 cpuguy83 deleted the handle_close_error_on_save branch July 15, 2020 16:35
@thaJeztah thaJeztah added this to the 20.03.0 milestone Aug 17, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants