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

In open(f, ...), call flush before calling close #35303

Closed
wants to merge 2 commits into from
Closed

Conversation

Keno
Copy link
Member

@Keno Keno commented Mar 30, 2020

In #35217, I noticed that if we call close on an IOStream, but the device
that has the underlying file is full, we silently truncate the file without
error. To remidy that, introduce an explicit flush call before closing the
file. This should either succeed and reflect the changes on disk, or fail
and throw an appropriate error.

In #35217, I noticed that if we call `close` on an IOStream, but the device
that has the underlying file is full, we silently truncate the file without
error. To remidy that, introduce an explicit flush call before closing the
file. This should either succeed and reflect the changes on disk, or fail
and throw an appropriate error.
Copy link
Member

@StefanKarpinski StefanKarpinski left a comment

Choose a reason for hiding this comment

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

👍

@KristofferC
Copy link
Member

[just stating the obvious, all CI failed because of errors in package loading]

@StefanKarpinski
Copy link
Member

While this is a good idea and should work, I fear that there are many kinds of IO objects where this will not work. I've seen it break things before. In general, I fear we seem to be in a state where the whole flush/close dance is very, very brittle.

Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

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

@StefanKarpinski This change should be fine. It's just implicit-return that got broken by mistake.

base/io.jl Outdated Show resolved Hide resolved
Copy link
Member

@vtjnash vtjnash left a comment

Choose a reason for hiding this comment

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

julia> open("VERSION") do f; close(f); flush(f); end

julia> open(`cat`, "w") do f; close(f); flush(f); end
ERROR: IOError: stream is closed or unusable

^ Do we have any tests like these?

@StefanKarpinski
Copy link
Member

StefanKarpinski commented Mar 30, 2020

If it works on all built-in IO types, I'll be happy (a little surprised, but happy), but I've definitely seen external IO types that I suspect would break with this change, e.g. TranscodingStreams.

@JeffBezanson
Copy link
Member

I'm also fine with this in theory but I'm worried about breakage. Why not add a call to flush in close(::IOStream) instead?

@JeffBezanson
Copy link
Member

Ah, in fact ios_close already calls ios_flush internally, it just doesn't report the error.

@Keno
Copy link
Member Author

Keno commented Mar 30, 2020

Ah, in fact ios_close already calls ios_flush internally, it just doesn't report the error.

Right, so the question is should close throw an error instead. And when we talked about it, the sense was that close should not error, which is why I'm proposing this instead.

The point is at some point, we should throw an error here, because otherwise subsequent code assumes that the file operation was complete, which may not be the case.

Co-Authored-By: Jameson Nash <[email protected]>
@JeffBezanson
Copy link
Member

It seems strange to me to only throw the error if you use the open(::Function,...) form. It also conflicts with having a more general with-style construct --- is the destructor/finalizer for a file close, or flush plus close? What do other systems do in this situation?

@Keno
Copy link
Member Author

Keno commented Mar 30, 2020

fclose returns an error code, but not sure if anybody ever checks it.

@JeffBezanson
Copy link
Member

close methods in Java and Python throw errors in this kind of situation, so I think it would be simpler and more consistent to propagate the error from the existing flush call inside close.

@StefanKarpinski
Copy link
Member

Agree. If write stuff and close a file and it didn't get successfully written to the file, I want an error.

@JeffBezanson
Copy link
Member

If flush fails inside close, should we continue closing the file anyway, or leave the file open? My gut reaction is that it's more predictable to close it no matter what, but that does mean you could lose buffered data.

@StefanKarpinski
Copy link
Member

Agree: close is better. If there's an error, you can't really assume the resulting file is in any kind of recoverable state anyway.

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.

5 participants