Open grapland0 opened 2 years ago
But that is exactly the purpose of the non_blocking_adapter? When a nonblocking sink returns 0 it should mean to try again later, and that's what it does. In case if a permanent error, the sink must in fact return -1. I've not found that documented, but the code seems clear and consistent about this... So why does the sink not return -1? If it can't know it's broken there is nothing that can be done really, since it's not possible to detect something is wrong.
According to https://www.boost.org/doc/libs/1_76_0/libs/iostreams/doc/functions/write.html , iostreams::write
simply returns t.rdbuf()->sputn(s, n)
in this case. sputn
can only return zero or greater, which looks like not being able to exit at any write error.
To detect whether the failure is permanent, do you think it should also check the fail/bad bit?
It's a bit hard to say without knowing why the sink device would become "broken" and how it is designed to report that. It could throw an exception when it breaks. Or it could signal it via pubsync() returning -1, which maybe should be called if the write unexpectedly returns 0? Though I am not sure if the combination of streambuf and non-blocking is making sense in the first place.
Looking at this again, https://www.boost.org/doc/libs/1_76_0/libs/iostreams/doc/guide/exceptions.html suggests that exceptions should be used to report errors. However iostream's own file_sink/source report read errors with -1 and write errors not at all. Does anyone have any idea/suggestion how this kind of issue could be fixed? E.g. full disk currently results in endless loop consuming 100% CPU.
boost version: 1.78 compiler: gcc version 11.2.0
typical stack trace:
At
boost/iostreams/detail/adapter/non_blocking_adapter.hpp:43
I found theiostreams::write
keeps return zero (due to the broken sink device), and it makes the loop starting at line 41 running forever.