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;
Isn't assigning to errno from non-libc code discouraged?
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.
I don't know. It really seems like something the operating system / C library does, not the user code.
No errno, no problem.
(removed this change at the expense of a less detailed error message)
As mentioned in #21630 (comment): a case for [[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)?
@vasild Yes, I still think it makes sense. (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]] :)
Code review ACK 1c1467f51b6dda92dec974eb59026c2c5ba79ed6
Checked that the exception is caught (in the same function, even). As this fixes a problem, I think whether to use [[nodiscard]] is scope for a separate PR.
cr ACK 1c1467f51b6dda92dec974eb59026c2c5ba79ed6: patch looks correct and agree with laanwj that [[nodiscard]] can be taken in a follow-up PR :)
(removed @ from OP)
(removed @ from review comment)
Milestone
22.0