call Sync() before Close() #279

Merged
merged 3 commits into from May 18, 2017

Conversation

Projects
None yet
3 participants
Member

gabriel-samfira commented May 5, 2017

On windows, disk cache and buffers are enabled by default. In the event of a power failure any file that has not yet flushed its contents to disk will become corupt. This leads to state files and agent configs being filled with garbage data.

fixes bug: https://bugs.launchpad.net/juju/+bug/1691193

call Sync() before Close()
On windows, disk cache and buffers are enabled by default. In the event of a power failure
any file that has not yet flushed its contents to disk will become corupt. This leads to state
files and agent configs being filled with garbage data.

@gabriel-samfira gabriel-samfira changed the title from disable disk cache and write buffer to call Sync() before Close() May 5, 2017

some more consistency fixes
When upgrading charms, in case of power failure, you end up with half written files. This change runs a sync() before an explicit close(). Thou shalt not defer Close().

The Sync() and Close() changes make sense - I think that since the file gets closed before calling change in AtomicWriteFileAndChange we should make the change func just take the file name.

+ }
+ if err := f.Close(); err != nil {
+ return err
+ }
@babbageclunk

babbageclunk May 17, 2017

Member

This seems wrong - you're closing the file before calling change with it? I guess that works ok in the case of AtomicWriteFile since the change func is just doing a chmod. But it doesn't seem right in general. Is there a reason for not just doing the sync and close after change?

@babbageclunk

babbageclunk May 17, 2017

Member

Ok, from talking in IRC I understand why you're doing this - the change func might fail on Windows if the file isn't closed. (Depending on what the change function is.)

@babbageclunk

babbageclunk May 17, 2017

Member

In that case though the interface should really be changed - the change func should be passed the file name instead of a closed *File. There's only one use of AtomicWriteFileAndChange in the whole codebase, so it's probably ok to update it.

@gabriel-samfira

gabriel-samfira May 17, 2017

Member

made the change. Also did a recursive grep throughout the code. The AtomicWriteFileAndChange function is only used in this package.

PTAL.

@babbageclunk

babbageclunk May 18, 2017

Member

Sorry, I missed this - your change here looks great though. Thanks!

@@ -155,6 +155,12 @@ func createAndFill(filePath string, mode int64, content io.Reader) error {
if err != nil {
return fmt.Errorf("cannot set proper mode on file %q: %v", filePath, err)
}
+ if err := fh.Sync(); err != nil {
@babbageclunk

babbageclunk May 17, 2017

Member

I started to say that it would be better to put this and the close into the defer and make them avoid clobbering any other errors being returned while still returning any errors from them, but actually it's unwieldy enough that I don't think it's worth doing.

change signature of change() function
pass in a filename to change instead of an *os.File
Member

gabriel-samfira commented May 18, 2017

$$merge$$

Contributor

jujubot commented May 18, 2017

Status: merge request accepted. Url: http://juju-ci.vapour.ws:8080/job/github-merge-juju-utils

@jujubot jujubot merged commit e126b30 into juju:master May 18, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment