On 1/6/22 10:03, Zebediah Figura wrote:
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52335 Signed-off-by: Zebediah Figura zfigura@codeweavers.com
dlls/ws2_32/tests/sock.c | 5 ++--- server/sock.c | 5 +++++ 2 files changed, 7 insertions(+), 3 deletions(-)
[snip]
diff --git a/server/sock.c b/server/sock.c index 736f34feac5..c7378306511 100644 --- a/server/sock.c +++ b/server/sock.c @@ -2543,6 +2543,11 @@ static void sock_ioctl( struct fd *fd, ioctl_code_t code, struct async *async ) sock->nonblocking = 1;
sock_reselect( sock );
/* Explicitly wake the socket up if the mask causes it to become
* signaled. Note that reselecting isn't enough, since we might already
* have had events recorded in sock->reported_events and we don't want
* to select for them again. */
sock_wake_up( sock );
On a second thought, I think it makes sense to follow up almost every call to sock_reselect() with a call to sock_wake_up().
Generally, an asynchronous socket object, which serves as an emulation layer between Unix non-blocking I/O and Windows asynchronous I/O, has to maintain two invariants at any poll() point (ditto for epoll, /dev/poll, or any other poll-like calls):
1. For all waiters (from WSAPoll, overlapped I/O or otherwise), the corresponding flags in the requested poll events mask are set.
2. For all flags set in the intersection (bitwise AND) of the requested poll events mask and the returned poll events mask, the correspoding waiters shall eventually be notified. (Note: assumes level-triggered events.)
As you have observed, sock_reselect() serves to establish invariant 1 but in the process disrupts invariant 2, since it updates flags without taking account the implicit changes to the set of notified waiters in the process of updating the mask.
In fact, I think it's sensible to merge sock_reselect() and sock_wake_up() in one function.
Any thoughts?
return; }