diff --git a/dlls/ws2_32/tests/sock.c b/dlls/ws2_32/tests/sock.c index 882bf226192..6356d9f474d 100644 --- a/dlls/ws2_32/tests/sock.c +++ b/dlls/ws2_32/tests/sock.c @@ -3133,10 +3133,10 @@ static void test_events(int useMessages) ok(ret == 2, "Failed to send buffer %d err %d\n", ret, GetLastError()); broken_seq[0] = read_read_seq; /* win9x */ broken_seq[1] = NULL; - if (useMessages) /* we like to erase pmask in server, so we have varying behavior here */ - todo_wine ok_event_seq(src, hEvent, empty_seq, broken_seq, 0); - else - ok_event_seq(src, hEvent, empty_seq, broken_seq, 0); + /* we like to erase pmask in server, so we have varying behavior here * + * it is only fixed for now because we refuse to send notifications with + * any kind of asyncs requests running */ + ok_event_seq(src, hEvent, empty_seq, broken_seq, 0); dwRet = WaitForSingleObject(ov.hEvent, 100); ok(dwRet == WAIT_OBJECT_0, "Failed to wait for recv message: %d - %d\n", dwRet, GetLastError()); diff --git a/server/async.c b/server/async.c index 73cd76de3e1..dd28dfffccd 100644 --- a/server/async.c +++ b/server/async.c @@ -276,6 +276,12 @@ void async_set_result( struct object *obj, unsigned int status, unsigned int tot } } +/* check if there are any queued async operations */ +int async_queued( struct async_queue *queue ) +{ + return queue && list_head( &queue->queue ); +} + /* check if an async operation is waiting to be alerted */ int async_waiting( struct async_queue *queue ) { diff --git a/server/file.h b/server/file.h index 03cea89bd58..9a348bfd572 100644 --- a/server/file.h +++ b/server/file.h @@ -146,6 +146,7 @@ extern struct async *create_async( struct thread *thread, struct async_queue *qu extern void async_set_timeout( struct async *async, timeout_t timeout, unsigned int status ); extern void async_set_result( struct object *obj, unsigned int status, unsigned int total, client_ptr_t apc ); +extern int async_queued( struct async_queue *queue ); extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); extern int async_wake_up_by( struct async_queue *queue, struct process *process, diff --git a/server/sock.c b/server/sock.c index d2348e4a147..34ec1768b77 100644 --- a/server/sock.c +++ b/server/sock.c @@ -255,28 +255,14 @@ static int sock_reselect( struct sock *sock ) } /* wake anybody waiting on the socket event or send the associated message */ -static void sock_wake_up( struct sock *sock, int pollev ) +static void sock_wake_up( struct sock *sock ) { unsigned int events = sock->pmask & sock->mask; int i; - int async_active = 0; - - if ( pollev & (POLLIN|POLLPRI|POLLERR|POLLHUP) && 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 ); - async_active = 1; - } - if ( pollev & (POLLOUT|POLLERR|POLLHUP) && 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 ); - async_active = 1; - } /* Do not signal events if there are still pending asynchronous IO requests */ /* We need this to delay FD_CLOSE events until all pending overlapped requests are processed */ - if ( !events || async_active ) return; + if ( !events || async_queued( sock->read_q ) || async_queued( sock->write_q ) ) return; if (sock->event) { @@ -437,7 +423,21 @@ static void sock_poll_event( struct fd *fd, int event ) } /* wake up anyone waiting for whatever just happened */ - if ( sock->pmask & sock->mask || sock->flags & WSA_FLAG_OVERLAPPED ) sock_wake_up( sock, event ); + sock_wake_up( sock ); + + if ( sock->flags & WSA_FLAG_OVERLAPPED ) + { + if ( event & (POLLIN|POLLPRI|POLLERR|POLLHUP) && 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 ); + } + if ( event & (POLLOUT|POLLERR|POLLHUP) && 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 ); + } + } /* if anyone is stupid enough to wait on the socket object itself, * maybe we should wake them up too, just in case? */ @@ -876,7 +876,7 @@ DECL_HANDLER(set_socket_event) it is possible that FD_CONNECT or FD_ACCEPT network events has happened before a WSAEventSelect() was done on it. (when dealing with Asynchronous socket) */ - if (sock->pmask & sock->mask) sock_wake_up( sock, pollev ); + sock_wake_up( sock ); if (old_event) release_object( old_event ); /* we're through with it */ release_object( &sock->obj );