Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upio error handling design #770
Conversation
kjpgit
added some commits
Jan 29, 2015
This comment has been minimized.
This comment has been minimized.
sinistersnare
commented
Jan 29, 2015
|
-1 this kinda disagrees with Rust's RAII in my opinion. |
This comment has been minimized.
This comment has been minimized.
|
I like the ideas in this, but am not sure at all if this should be applied to all kinds of Writers. I do think it is absolutely necessary for some Writers to force explicit errorhandling on close() |
This comment has been minimized.
This comment has been minimized.
|
Previous discussion: https://github.com/rust-lang/rfcs/pull/576/files#r23805711 |
This comment has been minimized.
This comment has been minimized.
|
@sinistersnare I think the link above explains why RAII doesn't work for some kinds of Writers. |
This comment has been minimized.
This comment has been minimized.
|
@sinistersnare RAII is a great way to release resources and that's what we're doing. An unflushed buffer in BufferWriter is being released. But what we're not doing is attempting to create new resources, e.g. on the filesystem, with no way to relay errors because we don't want to panic in a destructor. |
This comment has been minimized.
This comment has been minimized.
|
-1 The current way works well in practice which means that this RFC is a serious step backwards for most users. |
This comment has been minimized.
This comment has been minimized.
sinistersnare
commented
Jan 29, 2015
|
I feel like the sort of random panics that are trying to be prevented in this RFC are still in Rust in a few ways. For example, Basically, I do not think that the correctness benefit is greater than the ergonomic loss. However, if there is a resounding yes to this proposal, I am no language designer (I wish I was, but alas), so I wont be too upset it if was accepted. Thanks for the reading, I am currently procrastinating homework, but I will try to read that later :) |
This comment has been minimized.
This comment has been minimized.
|
I agree with you, but IMO it's less problematic with println, because if you want to explicitly handle errors, stdout.write is not too low-level. I suppose ideally Rust would have an API with explicit error checks, and one for the common usecase which panics on edgecases. |
This comment has been minimized.
This comment has been minimized.
|
There was a discussion about the same issue but for C++: the ideal semantics IMO, would be for the guard to flush and close the underlying stream iff it exits the scope normally, rather than as the result of a panic and stack unwinding. Errors from close result in a panic (to avoid this, close must be called explicitly and the errors handled) The problem is that it's impossible to implement this correctly using only a library method such as "is thread panicking" to be called from the destructor to determine whether to close() or not, because even during a panic, a guard within a destructor can exit scope normally. Possible implementation: add a "Closable" trait. The compiler will automatically insert calls to "close()" when a stack object implementing that trait leaves scope normally (ie. not as part of unwinding). For Closable objects constructed on the heap, it is up to the owner to call "close" explicitly. For example, Box<T: Closable> should itself implement Closable and forward on the calls as expected. |
kjpgit
added some commits
Jan 29, 2015
This comment has been minimized.
This comment has been minimized.
|
Thanks @Diggsey for that comment about a guard in a destructor. I added a note "Note that this can give a false negative" in the RFC, but I am doing the reverse logic as what you are suggesting. And +1 to your comment. I'm trying to decide if it's backwards compatible with my proposal. We could say implicit drop has undefined behavior if you didn't call close(), and leave it at that until Closeable happens, and then it changes to defined behavior - nothing happens unless it left scope normally, in which case it is closed, but then that could in theory cause panics in code that didn't before. |
This comment has been minimized.
This comment has been minimized.
|
@Diggsey the way to stop Closeable would be to explicit drop(myfile), right? In case you wanted to be future proof. e.g. in pseudocode: do_something_with(&my_file) I'm assuming there is potentially a use case somewhere where you don't want to flush and close the buffered file in some circumstance. |
This comment has been minimized.
This comment has been minimized.
|
@kjpgit Yeah, anything which consumes the Closable would prevent the compiler from emitting calls to close or drop as usual. The drop method itself shouldn't call close either, so that gives you a way to avoid it. I think adding Closeable later can be made backwards compatible, as long as a few conditions hold:
|
This comment has been minimized.
This comment has been minimized.
|
@Diggsey I'm still confused how the automagic scoped_close() method is prevented. drop is literally an empty function, and we want to move file objects around to new scopes. So both the close() method itself needs a way to take ownership, close resources, and drop without having the scope_close() called again. Same with the example code I did earlier. There seems to be a more magical drop() needed. |
This comment has been minimized.
This comment has been minimized.
|
Sorry I phrased that badly, when I said "drop" shouldn't call close, I meant it should be defined to not call close, not that it will already behave that way under the current implementation. |
This comment has been minimized.
This comment has been minimized.
|
@Diggsey I think the Closeable will unfortunately cause panics with people who are trying not to write panicing code. E.g. try!(my_file.close()); Is obviously designed not to panic, but if Closeable is the default, if my_file fails and try! tries to return an error, and then my_file2 also fails autoclose, it will cause a panic where there shouldn't have been one. |
kjpgit
added some commits
Jan 30, 2015
This comment has been minimized.
This comment has been minimized.
|
@mahkoh "The reason why rust "somewhat" works today is because Rust's stdout |
This comment has been minimized.
This comment has been minimized.
|
@kjpgit That's a difficult case - I'm starting to think that explicit close might be the best we can do. In combination with a lint it shouldn't be too bad. |
This comment has been minimized.
This comment has been minimized.
|
@kjpgit: I consider panic quite useless and would not mind having it replaced by abort. Either way, you wouldn't use println! and friends outside of toy programs. |
kjpgit
added some commits
Jan 30, 2015
aturon
referenced this pull request
Jan 30, 2015
Merged
Amend RFC 517: Revisions to reader/writer, core::io and std::io #576
pnkfelix
assigned
aturon
Feb 5, 2015
This comment has been minimized.
This comment has been minimized.
|
I think the use case to have |
This comment has been minimized.
This comment has been minimized.
|
To clarify the comment above: I support the need for |
This comment has been minimized.
This comment has been minimized.
|
Making the types that need explicit |
This comment has been minimized.
This comment has been minimized.
|
When we discussed this (fairly extensively) during IO reform, one of the basic questions was: what errors can you receive when trying to close a file that would not also arise by flushing it? That is, in what circumstances is calling cc @sfackler |
This comment has been minimized.
This comment has been minimized.
gkoz
commented
Mar 20, 2015
|
It's not a file... but a block mode cipher that's had an incomplete block of data written to it can't |
This comment has been minimized.
This comment has been minimized.
|
@gkoz That's an interesting example, but it's not clear why |
This comment has been minimized.
This comment has been minimized.
gkoz
commented
Mar 20, 2015
|
@aturon Generally, it could work but when doing foreign library bindings (e.g. rust-openssl) it's not always possible. Or rather I'd say openssl actively refuses to play by Rust's rules ;) (We could catch the case of unaligned end of data in block modes relatively easily, tracking padding would require some effort and overhead, the authentication case? well...) Isn't it also a bit odd for |
This comment has been minimized.
This comment has been minimized.
gkoz
commented
Mar 20, 2015
|
To rephrase the last point, is it appropriate for |
This comment has been minimized.
This comment has been minimized.
|
@aturon I'm confused. Are you inquiring about something besides what the close(2) NOTES section on linux talks about? |
This comment has been minimized.
This comment has been minimized.
|
The implementations of |
alexcrichton
referenced this pull request
Apr 14, 2015
Closed
Ignored errors in file handling #24413
alexcrichton
added
the
T-libs
label
May 18, 2015
This comment has been minimized.
This comment has been minimized.
|
This RFC is now entering its week-long final comment period. My personal feelings on this RFC is that while it may certainly be desirable to have a |
alexcrichton
added
the
final-comment-period
label
Jul 16, 2015
This comment has been minimized.
This comment has been minimized.
|
I agree with @alexcrichton; while there is a hypothetical need for this functionality, I think we have much bigger fish to fry with respect to IO, and I would prefer to wait on this until there is a more clear need for the functionality. It's worth noting that, especially with the forthcoming |
This comment has been minimized.
This comment has been minimized.
|
I'm not sure what bigger fish to fry there are than making sure data isn't On Thu, Jul 16, 2015 at 11:03 AM, Aaron Turon notifications@github.com
|
This comment has been minimized.
This comment has been minimized.
|
I, too, think it a pity that one needs more than the standard library to use the basic file functionality on POSIX systems with a degree of reliability that the developers are accustomed to (no hard write-through guarantee, but a number of easy-to-detect errors not going unreported either). Hiding a potentially blocking operation in the destructor without an explicit way to invoke it or drain the output buffer (files only have |
This comment has been minimized.
This comment has been minimized.
I think this is a bit hyperbolic to say, so it may not be 100% faithful to this RFC. We will always have primitives close themselves on drop, so receiving an error from the
I'm not sure this is a line of reasoning we can follow too far though as it's unclear how many possible designs there are in this space. As I mentioned above, we're always going to call It seems like we will fundamentally always close I/O objects on drop, and then we will also very likely provide the ability to manually close an object to see if any errors arise. It will always be an opt-in to seeing the error on |
This comment has been minimized.
This comment has been minimized.
The problem is that right now there isn't an obvious way to write to a file and check whether an error has occured. That's pretty fundamental if you ask me. To hyperbolize this point a bit, not checking the return value of I fail to understand how you can brush this off as a minor issue. :( |
This comment has been minimized.
This comment has been minimized.
|
As far as I understand On Fri, Jul 24, 2015 at 02:59:20PM -0700, tbu- wrote:
|
This comment has been minimized.
This comment has been minimized.
|
@untitaker |
This comment has been minimized.
This comment has been minimized.
main--
commented
Jul 25, 2015
|
@untitaker @tbu- As there seems to be confusion regarding Rust's current behavior:
|
This comment has been minimized.
This comment has been minimized.
|
The consensus of the libs team this week was to close this RFC. While it's something we may want to add to the standard library in the future, with the addition of Thanks again for the RFC @kjpgit! |
kjpgit commentedJan 29, 2015
thanks for reading!