If Sock::Wait()
fails, then cancel the Accept()
method.
Not checking the return value may cause an uninitialized read a few lines below when we read the occurred
variable.
Spotted by MarcoFalke, thanks!
105@@ -106,6 +106,7 @@ bool Sock::Wait(std::chrono::milliseconds timeout, Event requested, Event* occur
106 return true;
107 #else
108 if (!IsSelectableSocket(m_socket)) {
109+ errno = WSAEINVAL;
I don’t know, why would it be discouraged? There are already some assignments elsewhere in the code.
An alternative would be to introduce Wait()
’s own error codes, all of which except one map 1:1 to errno values (as returned by poll()
or select()
) and one extra error code for this case where the socket is not selectable. Doesn’t sound nice.
No errno, no problem.
(removed this change at the expense of a less detailed error message)
[[nodiscard]]
? :)
424246e46...1c1467f51
: ditch a change that set errno
and log a generic message if Sock::Wait()
fails.
@practicalswift in the SendComplete()
and RecvUntilTerminator()
methods and in sock_tests/wait
we call Wait()
without checking its return value and that’s ok. Do you think it is worth adding [[nodiscard]]
to Wait()
and complicating the callers to check it even though it is not necessary (or typecast to void
to just silence the newly added warning)?
(void)foo()
is the idiomatic way to express that one is intentionally ignoring the return value of foo()
. As always: explicit is better than implicit :)
@practicalswift, I agree in general. In this case however there are 6 callers in total, 3 of them check the return value and 3 would have to be cast to void
. Hmm, where is the threshold?
Also, the semantic of Wait()
is such that ignoring the return value is legit.
Anyway, [[nodiscard]]
is wider topic and is out of the scope of this PR. I will prepare another one to flag the relevant methods of Sock
with [[nodiscard]]
, but I am unsure whether Wait()
is one of them. What do you think, given the above?
@practicalswift, I agree in general. In this case however there are 6 callers in total, 3 of them check the return value and 3 would have to be cast to
void
. Hmm, where is the threshold?Also, the semantic of
Wait()
is such that ignoring the return value is legit.
I see your point, and your observation may be an indication that Wait
could be split up in two functions to cover the two different use cases.
In other words, one function which takes Event& occurred
which is annotated [[nodiscard]]
, and one with doesn’t take (or modify) occurred
at all and thus doesn’t need [[nodiscard]]
:)
[[nodiscard]]
is scope for a separate PR.
[[nodiscard]]
can be taken in a follow-up PR :)
@
from OP)
@
from review comment)