-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: io: document Closer as an idempotent operation #25390
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
Comments
If the first a Close returned an error, are subsequent calls required to return the same error? Conversely, if the first close returned no error, are subsequent calls required to return no error? |
Would it be more correct to update the documented for io.Closer to say
That would appear to address this issue without having to overly specify the outcome of calling Close more than once. |
Why is a panic considered a bad outcome given today's contract? It allows you to quickly pinpoint the issue and go on. I'm more worried about the cases where duplicate Close calls result in silent bogus actions (think os.File without its safeguards). Implementations of io.Closer are often wrappers around other systems where the close operation is not defined as idempotent or where duplicate close calls are plain illegal/undefined. This change would require all those io.Closers to keep a state flag (and possibly synchronization around it). I don't think this can possibly be a Go1 change. |
That's not wording we can really use for an interface. We can only document the actual behavior for concrete types (you used the word "is"). For an interface, we can only say "should" or "must not", etc. |
When the io.Closer docs say "The behavior of Close after the first call is undefined.", that means callers may not assume anything and that implementations may do anything they like. We can't retroactively change that, not without causing many (most?) existing implementations to become invalid. We should probably leave well enough alone for now. At most we could add a suggestion that implementations be idempotent, but users of a general io.Closer still must not assume that. |
Per previous comment, we're pretty well locked in at this point. We can't redefine the interface. There are a few APIs where Close means "commit" and maybe we should look at this separately. But io.Closer is what it is. |
The documented behavior of
io.Closer
is:The fact that the behavior of a second call to
Close
is undefined means that an implementation may actually panic. Unfortunately, too many callers ofClose
make the assumption that the call is safe to make twice. For example:The documentation regarding undefined behavior was made 5 years ago by @bradfitz because he observed people making this assumption. However, time has demonstrated that people still widely assume
Close
to be idempotent.Thus, I propose changing the documentation to match what people expect:
This may need to be a Go2 change, but it may be worth considering today given how pervasive the assumption already is.
The text was updated successfully, but these errors were encountered: