WSARecv call should not intercept message for the waiting overlapped WSARecv. To do that, We should know if waiting asyncs exist before trying ws2_recv/ws2_send.
Signed-off-by: Dongwan Kim dongwan_kim@tmax.co.kr --- dlls/ws2_32/socket.c | 31 +++++++++++++++++++++++++++++-- include/wine/server_protocol.h | 20 +++++++++++++++++++- server/protocol.def | 8 ++++++++ server/request.h | 8 ++++++++ server/sock.c | 28 ++++++++++++++++++++++++++++ server/trace.c | 12 ++++++++++++ 6 files changed, 104 insertions(+), 3 deletions(-)
diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 2776e2f0014..752ece2bc7d 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1967,6 +1967,23 @@ static void WINAPI ws2_async_apc( void *arg, IO_STATUS_BLOCK *iosb, ULONG reserv release_async_io( &wsa->io ); }
+/* query if the socket has pending asyncs */ +static int WS_QueryAsyncWaiting( SOCKET sock, int type ) +{ + int result=0; + + SERVER_START_REQ( query_async_waiting ) + { + req->handle = wine_server_obj_handle( SOCKET2HANDLE(sock) ); + req->type = type; + wine_server_call(req); + result = reply->state; + } + SERVER_END_REQ; + return result; + +} + /*********************************************************************** * WS2_recv (INTERNAL) * @@ -5099,7 +5116,12 @@ static int WS2_sendto( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, }
flags = convert_flags(dwFlags); - n = WS2_send( fd, wsa, flags ); + if(WS_QueryAsyncWaiting(s , ASYNC_TYPE_WRITE)) + { + n = -1; errno = EAGAIN; + } + else + n = WS2_send( fd, wsa, flags ); if (n == -1 && errno != EAGAIN) { err = wsaErrno(); @@ -6179,7 +6201,12 @@ static int WS2_recv_base( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, flags = convert_flags(wsa->flags); for (;;) { - n = WS2_recv( fd, wsa, flags ); + if(WS_QueryAsyncWaiting(s, ASYNC_TYPE_READ)) + { + n = -1; errno = EAGAIN; + } + else + n = WS2_recv( fd, wsa, flags ); if (n == -1) { /* Unix-like systems return EINVAL when attempting to read OOB data from diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 8ae313e6581..b61ef526dff 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -5391,6 +5391,21 @@ struct get_next_thread_reply char __pad_12[4]; };
+struct query_async_waiting_request +{ + struct request_header __header; + obj_handle_t handle; + int type; + char __pad_20[4]; + +}; +struct query_async_waiting_reply +{ + struct reply_header __header; + int state; + char __pad_12[4]; +}; +
enum request { @@ -5668,6 +5683,7 @@ enum request REQ_suspend_process, REQ_resume_process, REQ_get_next_thread, + REQ_query_async_waiting, REQ_NB_REQUESTS };
@@ -5949,6 +5965,7 @@ union generic_request struct suspend_process_request suspend_process_request; struct resume_process_request resume_process_request; struct get_next_thread_request get_next_thread_request; + struct query_async_waiting_request query_async_waiting_request; }; union generic_reply { @@ -6228,11 +6245,12 @@ union generic_reply struct suspend_process_reply suspend_process_reply; struct resume_process_reply resume_process_reply; struct get_next_thread_reply get_next_thread_reply; + struct query_async_waiting_reply query_async_waiting_reply; };
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 697 +#define SERVER_PROTOCOL_VERSION 698
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index 9361933d47c..58b1d5c4136 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -3699,3 +3699,11 @@ struct handle_info @REPLY obj_handle_t handle; /* next thread handle */ @END + +/* Query if there are waiting asyncs of the socket */ +@REQ(query_async_waiting) + obj_handle_t handle; /* socket handle */ + int type; /* async type */ +@REPLY + int state; /* waiting async exists */ +@END diff --git a/server/request.h b/server/request.h index ec5595bedf2..450667e9cf3 100644 --- a/server/request.h +++ b/server/request.h @@ -393,6 +393,7 @@ DECL_HANDLER(terminate_job); DECL_HANDLER(suspend_process); DECL_HANDLER(resume_process); DECL_HANDLER(get_next_thread); +DECL_HANDLER(query_async_waiting);
#ifdef WANT_REQUEST_HANDLERS
@@ -673,6 +674,7 @@ static const req_handler req_handlers[REQ_NB_REQUESTS] = (req_handler)req_suspend_process, (req_handler)req_resume_process, (req_handler)req_get_next_thread, + (req_handler)req_query_async_waiting, };
C_ASSERT( sizeof(abstime_t) == 8 ); @@ -2236,6 +2238,12 @@ C_ASSERT( FIELD_OFFSET(struct get_next_thread_request, flags) == 28 ); C_ASSERT( sizeof(struct get_next_thread_request) == 32 ); C_ASSERT( FIELD_OFFSET(struct get_next_thread_reply, handle) == 8 ); C_ASSERT( sizeof(struct get_next_thread_reply) == 16 ); +C_ASSERT( FIELD_OFFSET(struct query_async_waiting_request, handle) == 12 ); +C_ASSERT( FIELD_OFFSET(struct query_async_waiting_request, type) == 16 ); +C_ASSERT( sizeof(struct query_async_waiting_request) == 24 ); +C_ASSERT( FIELD_OFFSET(struct query_async_waiting_reply, state) == 8 ); +C_ASSERT( sizeof(struct query_async_waiting_reply) == 16 ); +
#endif /* WANT_REQUEST_HANDLERS */
diff --git a/server/sock.c b/server/sock.c index 39f02036da8..59023d81630 100644 --- a/server/sock.c +++ b/server/sock.c @@ -1889,3 +1889,31 @@ DECL_HANDLER(get_socket_info)
release_object( &sock->obj ); } + +DECL_HANDLER( query_async_waiting ) +{ + struct sock *sock; + struct async *async; + reply->state = 0; + + if (!(sock = (struct sock *)get_handle_obj( current->process, req->handle, + FILE_READ_ATTRIBUTES, &sock_ops))) return; + if (get_unix_fd( sock->fd ) == -1) return; + + if (is_fd_overlapped( sock->fd )) + { + if(req->type == ASYNC_TYPE_READ && ( async = find_pending_async(&sock->read_q) )) { + reply->state = 1; + release_object(async); + } + if(req->type == ASYNC_TYPE_WRITE && ( async = find_pending_async(&sock->write_q )) ) + { + reply->state = 1; + release_object(async); + } + } + release_object( &sock->obj ); + +} + + diff --git a/server/trace.c b/server/trace.c index 5dfb40bb2ac..b38233a7162 100644 --- a/server/trace.c +++ b/server/trace.c @@ -4449,6 +4449,15 @@ static void dump_get_next_thread_reply( const struct get_next_thread_reply *req { fprintf( stderr, " handle=%04x", req->handle ); } +static void dump_query_async_waiting_request( const struct query_async_waiting_request *req ) +{ + fprintf( stderr, " handle=%04x", req->handle ); + fprintf( stderr, ", type=%d", req->type ); +} +static void dump_query_async_waiting_reply( const struct query_async_waiting_reply *req ) +{ + fprintf( stderr, " state=%d", req->state ); +}
static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_new_process_request, @@ -4725,6 +4734,7 @@ static const dump_func req_dumpers[REQ_NB_REQUESTS] = { (dump_func)dump_suspend_process_request, (dump_func)dump_resume_process_request, (dump_func)dump_get_next_thread_request, + (dump_func)dump_query_async_waiting_request, };
static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { @@ -5002,6 +5012,7 @@ static const dump_func reply_dumpers[REQ_NB_REQUESTS] = { NULL, NULL, (dump_func)dump_get_next_thread_reply, + (dump_func)dump_query_async_waiting_reply, };
static const char * const req_names[REQ_NB_REQUESTS] = { @@ -5279,6 +5290,7 @@ static const char * const req_names[REQ_NB_REQUESTS] = { "suspend_process", "resume_process", "get_next_thread", + "query_async_waiting", };
static const struct
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=90103
Your paranoid android.
=== debiant2 (build log) ===
error: patch failed: include/wine/server_protocol.h:6228 Task: Patch failed to apply
=== debiant2 (build log) ===
error: patch failed: include/wine/server_protocol.h:6228 Task: Patch failed to apply