Hi Everyone, Stream operations often return error codes (they still throw exceptions) and I am trying to wrap my head around how they can be processed. Functions pull_from and push_to special-case on cond::eof. So do a number of examples in the docs. Why only this one? I have been told that cond::stream_truncated means "end of file, transmission ended before the handshake, may be a truncation attack, may be a safe end, judge yourself." How can users make this call when some Capy functions already discard it? BTW, looking at the implementation of pull_from and push_to, when an error is reported, there is no way to figure out from which stream it originated. Looking at the implementation in normalize_openssl_shutdown_read_error in Corosio, it looks like when we decide to stop a task reading an SSL stream we will not get cond::canceled, but instead we may get cond::stream_truncated. This is the only place where -- against the protocol -- we do not get the feedback that the operation was canceled as requested. BTW, cond::canceled detects two things: a successfully processed cancellation request (error::canceled) and other events, possibly caused by the state of the socket at the other end.(std::errc::operation_canceled). It is not a practical condition. Regards, &rzej;
On Wednesday, July 1st, 2026 at 12:49 AM, Andrzej Krzemienski via Boost <boost@lists.boost.org> wrote:
Functions pull_from and push_to special-case on cond::eof. So do a number of examples in the docs. Why only this one? I have been told that cond::stream_truncated means "end of file, transmission ended before the handshake, may be a truncation attack, may be a safe end, judge yourself."
The pumps treats eof specially because it is the only situation in which we can finalize the sink (commit_eof). On the stream version you get success, on the sink versions if commit succeeds you get success or the ec from committing. This seems consistent.
How can users make this call when some Capy functions already discard it?
Where does Capy discard it? It should bubble up through ec.
BTW, looking at the implementation of pull_from and push_to, when an error is reported, there is no way to figure out from which stream it originated.
I think you're right about this and we should fix it.
Looking at the implementation in normalize_openssl_shutdown_read_error in Corosio, it looks like when we decide to stop a task reading an SSL stream we will not get cond::canceled, but instead we may get cond::stream_truncated. This is the only place where -- against the protocol -- we do not get the feedback that the operation was canceled as requested.
Yes, I think the mapping to stream_truncated is too aggressive. It should be addressed as well.
BTW, cond::canceled detects two things: a successfully processed cancellation request (error::canceled) and other events, possibly caused by the state of the socket at the other end.(std::errc::operation_canceled). It is not a practical condition.
cond::canceled should answer "was this canceled?," that seems like the correct usage of cond. If you want to know specifics you could check against specific error codes.
śr., 1 lip 2026 o 17:12 Steve Gerbino via Boost <boost@lists.boost.org> napisał(a):
On Wednesday, July 1st, 2026 at 12:49 AM, Andrzej Krzemienski via Boost < boost@lists.boost.org> wrote:
Functions pull_from and push_to special-case on cond::eof. So do a number of examples in the docs. Why only this one? I have been told that cond::stream_truncated means "end of file, transmission ended before the handshake, may be a truncation attack, may be a safe end, judge yourself."
The pumps treats eof specially because it is the only situation in which we can finalize the sink (commit_eof). On the stream version you get success, on the sink versions if commit succeeds you get success or the ec from committing. This seems consistent.
How can users make this call when some Capy functions already discard it?
Where does Capy discard it? It should bubble up through ec.
Suppose that in my program I trust the senders. I know that they deliberately do not complete the final closing ceremony for performance reasons. I treat (or want to treat) stream_truncated as eof (successfully having read all bytes). Then I cannot use these pump functions, because they will refuse to commit on this "stream_truncated treated as eof" result.
BTW, looking at the implementation of pull_from and push_to, when an error is reported, there is no way to figure out from which stream it originated.
I think you're right about this and we should fix it.
Looking at the implementation in normalize_openssl_shutdown_read_error in Corosio, it looks like when we decide to stop a task reading an SSL stream we will not get cond::canceled, but instead we may get cond::stream_truncated. This is the only place where -- against the protocol -- we do not get the feedback that the operation was canceled as requested.
Yes, I think the mapping to stream_truncated is too aggressive. It should be addressed as well.
BTW, cond::canceled detects two things: a successfully processed cancellation request (error::canceled) and other events, possibly caused by the state of the socket at the other end.(std::errc::operation_canceled). It is not a practical condition.
cond::canceled should answer "was this canceled?," that seems like the correct usage of cond. If you want to know specifics you could check against specific error codes.
Expression "was this canceled" bears so many different meanings, covers so many unrelated situations, that I cannot see how it makes value to treat them collectively. The situation that I may need to distinguish is "I did not finish your task because you didn't want me to". But cond::canceled is not this. It also tells me that the operating system on the remote host decided to kill the connection. Why do you add this condition when the nebulous std::errc::operation_canceled already exists? Regards, &rzej; _______________________________________________
Boost mailing list -- boost@lists.boost.org To unsubscribe send an email to boost-leave@lists.boost.org https://lists.boost.org/mailman3/lists/boost.lists.boost.org/ Archived at: https://lists.boost.org/archives/list/boost@lists.boost.org/message/RKUJE4L3...
On Thursday, July 2nd, 2026 at 1:16 AM, Andrzej Krzemienski via Boost <boost@lists.boost.org> wrote:
Suppose that in my program I trust the senders. I know that they deliberately do not complete the final closing ceremony for performance reasons. I treat (or want to treat) stream_truncated as eof (successfully having read all bytes). Then I cannot use these pump functions, because they will refuse to commit on this "stream_truncated treated as eof" result.
In this case you're expected to handle it yourself as we cannot make that assumption. The pump will commit all bytes before checking and returning the error. You can handle it like this: auto [ec, n] = co_await pull_from(stream, sink); if(ec == cond::stream_truncated) // trusted peer, treat as eof auto [ec2] = co_await sink.commit_eof(0);
Expression "was this canceled" bears so many different meanings, covers so many unrelated situations, that I cannot see how it makes value to treat them collectively. The situation that I may need to distinguish is "I did not finish your task because you didn't want me to". But cond::canceled is not this. It also tells me that the operating system on the remote host decided to kill the connection. Why do you add this condition when the nebulous std::errc::operation_canceled already exists?
The simple answer is uniform vocabulary. The same thing applies to std::errc::timed_out. There is no standard error condition for stream_truncated or eof so we'd have to say for some errors compare against a capy::cond and others a std::errc. You are given tools to check conditions all within capy::cond and the documentation recommends it. A remote connection closing would be a connection_reset, so you can tell the difference. I checked and this is working properly on POSIX environments, though it seems that Windows requires some additional mapping and it is missing. I've added an issue to track this work: https://github.com/cppalliance/corosio/issues/304
participants (2)
-
Andrzej Krzemienski -
Steve Gerbino