This is validated by tests introduced in 59beffb46c813a3de2eae6f28e3f7f321f666e89 etc. This commit alone doesn't fix said tests, because:
* on this poll, we will alert the waiting async;
* when reselecting, we will still request POLLIN, because the AFD_POLL_READ request is still active,
* when POLLIN is subsequently signaled, we do not remove it in sock_dispatch_asyncs(), because we check async_waiting(), not async_queued().
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/sock.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/server/sock.c b/server/sock.c index 29dd1ca7fa8..db0df5ecf79 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1179,10 +1179,9 @@ static void sock_poll_event( struct fd *fd, int event ) break; }
- complete_async_polls( sock, event, error ); - event = sock_dispatch_asyncs( sock, event, error ); sock_dispatch_events( sock, prevstate, event, error ); + complete_async_polls( sock, event, error );
sock_reselect( sock ); }
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/afd.c | 2 +- server/sock.c | 34 +++++++++++++++++++++------------- 2 files changed, 22 insertions(+), 14 deletions(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c index cf27b4003c5..2ace83f5e21 100644 --- a/dlls/ws2_32/tests/afd.c +++ b/dlls/ws2_32/tests/afd.c @@ -382,7 +382,7 @@ static void test_poll(void) ok(size == 1, "got size %lu\n", size);
ret = WaitForSingleObject(event, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %#x\n", ret); + ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
ret = send(client, "a", 1, 0); ok(ret == 1, "got %d\n", ret); diff --git a/server/sock.c b/server/sock.c index db0df5ecf79..cf25994c383 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1229,6 +1229,18 @@ static int sock_get_poll_events( struct fd *fd ) if (!sock->type) /* not initialized yet */ return -1;
+ LIST_FOR_EACH_ENTRY( req, &poll_list, struct poll_req, entry ) + { + unsigned int i; + + for (i = 0; i < req->count; ++i) + { + if (req->sockets[i].sock != sock) continue; + + ev |= poll_flags_from_afd( sock, req->sockets[i].mask ); + } + } + switch (sock->state) { case SOCK_UNCONNECTED: @@ -1271,7 +1283,15 @@ static int sock_get_poll_events( struct fd *fd ) } else if (async_queued( &sock->read_q )) { - if (async_waiting( &sock->read_q )) ev |= POLLIN | POLLPRI; + /* Clear POLLIN and POLLPRI if we have an alerted async, even if + * we're polling this socket for READ or OOB. We can't signal the + * poll if the pending async will read all of the data [cf. the + * matching logic in sock_dispatch_asyncs()], but we also don't + * want to spin polling for POLLIN if we're not going to use it. */ + if (async_waiting( &sock->read_q )) + ev |= POLLIN | POLLPRI; + else + ev &= ~(POLLIN | POLLPRI); } else { @@ -1302,18 +1322,6 @@ static int sock_get_poll_events( struct fd *fd ) break; }
- LIST_FOR_EACH_ENTRY( req, &poll_list, struct poll_req, entry ) - { - unsigned int i; - - for (i = 0; i < req->count; ++i) - { - if (req->sockets[i].sock != sock) continue; - - ev |= poll_flags_from_afd( sock, req->sockets[i].mask ); - } - } - return ev; }
Asyncs which are alerted but not "waiting" may still consume all data, and we shouldn't signal AFD_POLL_READ or AFD_POLL_OOB in that case.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/sock.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/server/sock.c b/server/sock.c index cf25994c383..2bb2963a840 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1001,10 +1001,13 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) if ((event & POLLOUT) && sock->connect_req && sock->connect_req->iosb->status == STATUS_PENDING) complete_async_connect( sock );
- if (event & (POLLIN | POLLPRI) && async_waiting( &sock->read_q )) + if ((event & (POLLIN | POLLPRI)) && async_queued( &sock->read_q )) { - if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock ); - async_wake_up( &sock->read_q, STATUS_ALERTED ); + if (async_waiting( &sock->read_q )) + { + if (debug_level) fprintf( stderr, "activating read queue for socket %p\n", sock ); + async_wake_up( &sock->read_q, STATUS_ALERTED ); + } event &= ~(POLLIN | POLLPRI); }
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/sock.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/server/sock.c b/server/sock.c index 2bb2963a840..cb76765e495 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1315,7 +1315,12 @@ static int sock_get_poll_events( struct fd *fd )
if (async_queued( &sock->write_q )) { - if (async_waiting( &sock->write_q )) ev |= POLLOUT; + /* As with read asyncs above, clear POLLOUT if we have an alerted + * async. */ + if (async_waiting( &sock->write_q )) + ev |= POLLOUT; + else + ev &= ~POLLOUT; } else if (!sock->wr_shutdown && (mask & AFD_POLL_WRITE)) {
Asyncs which are alerted but not "waiting" may still fill the pipe, and we shouldn't signal AFD_POLL_WRITE in that case.
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- server/sock.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/server/sock.c b/server/sock.c index cb76765e495..aa62a03d699 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1011,10 +1011,13 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) event &= ~(POLLIN | POLLPRI); }
- if (event & POLLOUT && async_waiting( &sock->write_q )) + if ((event & POLLOUT) && async_queued( &sock->write_q )) { - if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock ); - async_wake_up( &sock->write_q, STATUS_ALERTED ); + if (async_waiting( &sock->write_q )) + { + if (debug_level) fprintf( stderr, "activating write queue for socket %p\n", sock ); + async_wake_up( &sock->write_q, STATUS_ALERTED ); + } event &= ~POLLOUT; }
Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- dlls/ws2_32/tests/afd.c | 2 +- dlls/ws2_32/tests/sock.c | 4 ++-- server/sock.c | 1 + 3 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/tests/afd.c b/dlls/ws2_32/tests/afd.c index 2ace83f5e21..5b64ccd7715 100644 --- a/dlls/ws2_32/tests/afd.c +++ b/dlls/ws2_32/tests/afd.c @@ -722,7 +722,7 @@ static void test_poll(void) ok(!size, "got size %lu\n", size);
ret = WaitForSingleObject(event, 0); - todo_wine ok(ret == WAIT_TIMEOUT, "got %#x\n", ret); + ok(ret == WAIT_TIMEOUT, "got %#x\n", ret);
closesocket(server); closesocket(client); diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 99221ad52ca..6e2e49c9178 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -5578,7 +5578,7 @@ static void test_accept_events(struct event_test_ctx *ctx) ok(ret, "got error %lu\n", GetLastError()); ok(!size, "got size %lu\n", size);
- check_events_todo(ctx, 0, 0, 0); + check_events(ctx, 0, 0, 0);
closesocket(server); closesocket(client); @@ -5587,7 +5587,7 @@ static void test_accept_events(struct event_test_ctx *ctx) ret = connect(client, (struct sockaddr *)&destaddr, sizeof(destaddr)); ok(!ret, "got error %u\n", WSAGetLastError());
- check_events_todo(ctx, FD_ACCEPT, 0, 200); + check_events(ctx, FD_ACCEPT, 0, 200); check_events(ctx, 0, 0, 0);
server = accept(listener, NULL, NULL); diff --git a/server/sock.c b/server/sock.c index aa62a03d699..e46be9349e2 100644 --- a/server/sock.c +++ b/server/sock.c @@ -990,6 +990,7 @@ static int sock_dispatch_asyncs( struct sock *sock, int event, int error ) if (req->iosb->status == STATUS_PENDING && !req->accepted) { complete_async_accept( sock, req ); + event &= ~POLLIN; break; } }