Re: [asio-users] asio and good error handling
Brought to you by:
chris_kohlhoff
From: Vinícius d. S. O. <vin...@gm...> - 2018-12-28 01:59:00
|
Em qui, 27 de dez de 2018 às 19:01, Jeff Abrahamson <je...@p2...> escreveu: > I've not found any good examples or guidelines for how to handle > different errors, perhaps along the lines of "if you get the this error > while reading data, then this is a good action to take". I know this > isn't one size fits all, but I also know that I don't want to wait > around for less common errors just to figure out what triggered them and > how to handle them. Even relatively straight-forward things like > connection_refused (ECONNREFUSED) can be a bit sticky: do I always want > to close and shutdown the socket or are their cases where that's > excessive? Maybe if I'm the client, but if I'm the server I can't > reconnect, I'm accepting and talking to an ephemeral port on the client. > > Thanks for any pointers. > Boost.Asio's core error handling transport is boost::system::error_code. There is nothing magical to unwrap out of this abstraction. It is a 2-tuple with a numerical error code (an enum) and a domain. The first component is like errno. If you and I try to extend the error types, we may hit code clash as we try to use the same numerical value for different error codes. That's why there is the error category which acts as an error domain. However I found hard to grasp the difference between error code and error condition. The “portable” name sometimes associated as the difference has given me no hints as to whenever to use each one. The following posts have enlightening information/examples as to this other matter (so do pay attention): - http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-1.html - http://blog.think-async.com/2010/04/system-error-support-in-c0x-part-2.html - http://breese.github.io/2017/05/12/customizing-error-codes.html As to the main point of your question, which is trying to figure it out which errors can arise out of which operations. That's a harder question to answer. That's a question that can only be answered if you narrow it to a specific platform. Once a platform has been chosen, you can read the platform's manual (e.g. the Linux Programmer's Manual manpages if you're on Linux) to have the answer. Many errors will only happen on specific circumstances (e.g. EINTR on Linux's read() will only happen if a signal is sent to the thread, ...). Also, IO errors are open-ended/unbounded and new error types can arise in the future. For instance, modern file systems are known to employ compression and you could get an insufficient space error just by flipping one byte that changes the compression ratio and suddenly there is no more space even thou you're adding no new bytes to the filesystem (this error would never happen on FAT32). For this reason, Rust developers behind io::ErrorKind gave it special treatment (you can never perform an exhaustive match on them without adding a wildcard match): https://github.com/rust-lang/rust/blob/fb86d604bf65c3becd16180b56267a329cf268d5/src/libstd/io/error.rs#L90 But I witnessed some very intelligent Rust developers, but with not-so-much real-world experience in programming and far too much mathematical background[1] to bias their judgement to unwelcome this decision. They miss the point. IO is just the closest we get to the border between our closed abstractions and an open world and are the region most affected by incomplete modelling. “The means whereby to identify dead forms is Mathematical Law. The means whereby to understand living forms is Analogy.” — O. Spengler “Mathematizing represents a very simple and easy human activity, because it deals with fictitious entities with all particulars included, and we proceed by remembering. [...] Physical or daily-life abstractions differ considerably from mathematical abstractions. [...] In general, physical abstractions, including daily-life abstractions are such that particulars are left out — we proceed by a process of forgetting. In other words, no description or ‘definition’ will ever include all particulars.” — Korzybski “This fact has significant ramifications when considering the availability vs. consistency tradeoff that was purported by the CAP theorem. It is not the case that if we guarantee consistency, we have to give up the guarantee of availability. We never had a guarantee of availability in the first place! Rather, guaranteeing consistency causes a reduction to our already imperfect availability.” — http://dbmsmusings.blogspot.com/2018/09/newsql-database-systems-are-failing-to.html (the last quote/example is a trick that I myself have fallen into) And last, as for your request for a “general strategies” to adopt on error handling, I feel this request is more appropriate to a “design patterns book” than to Boost.Asio documentation. It'll really depend a lot on your use case and I don't feel it is necessary for Boost.Asio examples to show any error handling strategy besides showing an error message and aborting operation. [1] other programmers with “far too much mathematical background” didn't fall for this trap, so “too much mathematics” is not a problem here at all and the problem is something else (maybe a confusion in the orders of abstractions) -- Vinícius dos Santos Oliveira https://vinipsmaker.github.io/ |