8 ms·
Yep, there's not really any such thing (IME) as a 'recoverable' error - except with respect to I/O. There's either I/O errors - or there's logic errors. A fail
by arcticbull 4y ago
Yep, there's not really any such thing (IME) as a 'recoverable' error - except with respect to I/O.
There's either I/O errors - or there's logic errors. A failure with logic should nuke due to the app being in an inconsistent state; trust is lost. An I/O error should fail softly.
- ithkuil 4y agoA parser library can return an error when the input is wrong. It doesn't necessarily mean the app is in an inconsistent state when that happens; it all depends on what the application does. It follows that aborting is often a sensible decision in application code and rarely in library code.
- arcticbull 4y agoI would personally consider parsers as part of I/O, but point taken.
- fatherzine 4y agoPartially true. In practice people implement multiplexed servers, for many reasons, including performance / throughput. A logic failure should nuke _the offending request_, not the entire server with all the unrelated concurrent requests.
- AshamedCaptain 4y agoThis is an attitude that I often see -- library authors who believe they own the process. Aborting may be the only sensible thing to do in runtimes where you can end up corrupting the entire process memory or the like, making recovery "dubiously possible", but absolutely not for anything higher level, where recovery may be safe and possible.
- burntsushi 4y agoI gave examples covering this area in the post. How would you rewrite the code in this section[1], for example, to conform to your views? (Assume this code is in a library.) [1]: https://blog.burntsushi.net/unwrap/#what-about-when-invariants-cant-be-moved-to-compile-time https://blog.burntsushi.net/unwrap/#what-about-when-invarian...
- fatherzine 4y ago* Short term: add explicit runtime checks for every step that may panic. With the way jump prediction works in modern processors, the runtime cost may be smaller than one may naively assume it is. Some of us would take, say, a 10% perf. degradation instead of chasing prod panics in the middle of the night. * Long term: plug-in a richer type (logic) system, so one can safely prove the most costly runtime invariants at compile time.
- burntsushi 4y ago> add explicit runtime checks for every step that may panic And do... what when the check fails? Can you please write the code for it? Because I don't understand what the heck you mean here. If you don't know Rust, pseudo code is fine. > Long term: plug-in a richer type (logic) system, so one can safely prove the most costly runtime invariants at compile time. This is just copying what I already said in the blog post. Until someone can show me how to prove the correctness of arbitrary DFA construction and search from a user provided regular expression pattern and demonstrate its use in a practical programming language like Rust, I consider this a total non-answer, not a "long term" answer. Basically, your answer here confirms for me that your views on how code should be structured are incoherent.
- fatherzine 4y agofn is_match(&self, haystack: &[u8]) -> Result<bool, Error> { ... }
- burntsushi 4y ago
- jcelerier 4y ago> There's either I/O errors - or there's logic errors. A failure with logic should nuke due to the app being in an inconsistent state; trust is lost. nah. in GUI apps for instance you want the failure in the logic of a sub-sub-function to just tell the error "wops" when the button that triggered the action was clicked, not nuke the app (unless you hate your users). e.g. imagine a 3D software which allows to do mesh operations - user clicks on the "Smooth the mesh" button somewhere. Programmer forgot to handle a division by zero in some degenerate case of the smoothing computation which ends up leading to an exception: a value becomes zero, someone used unsigned integers for n in an "n - 1" computation which ends up in a call to array_of_floats.resize(0xffffffffffffffff) (and a likely std::bad_alloc being thrown if you're in c++). The original mesh is unchanged as the operation waits until the computation is complete to replace the old mesh with the new. If you ever decide to crash in this situation I am sure you will have great reviews on 3D modeling software comparisons.
- arcticbull 4y agoI would actually want that to crash, yes. That would ensure it gets caught and resolved by developers during development. Or at least increase the odds thereof. Further, if it allocates a few gb, or if it's allocating a large amount of memory because the size parameter got smashed? If it crashes enough that you'd get terrible reviews it would definitely be caught during development. If it messes up your mesh silently then you'll definitely still get bad reviews. And actually having an std::bad_alloc thrown is even worse since you have no idea what state it left things after running some destructors when you weren't planning for it.
- jcelerier 4y ago> That would ensure it gets caught and resolved by developers during development i don't know in which reality you live but in mine there's not much relationship between the existence of crashes, and them being resolved during development > And actually having an std::bad_alloc thrown is even worse since you have no idea what state it left things after running some destructors when you weren't planning for it. i don't even know what to say. that's the whole point of destructors - you know that things will be unwound in the reverse order from which they were created on automatic storage. that's, like, why c++ exists