server: Check if we have waiting asyncs in (send_socket) before enforcing blocking send.
This commit is contained in:
parent
294efcdf44
commit
aac0998262
4 changed files with 54 additions and 1 deletions
|
@ -3106,6 +3106,29 @@ static test_setup tests [] =
|
|||
}
|
||||
};
|
||||
|
||||
struct send_udp_thread_param
|
||||
{
|
||||
int sock;
|
||||
HANDLE start_event;
|
||||
};
|
||||
|
||||
static DWORD WINAPI send_udp_thread( void *param )
|
||||
{
|
||||
struct send_udp_thread_param *p = param;
|
||||
static char buf[256];
|
||||
unsigned int i;
|
||||
int ret;
|
||||
|
||||
WaitForSingleObject( p->start_event, INFINITE );
|
||||
for (i = 0; i < 256; ++i)
|
||||
{
|
||||
ret = send( p->sock, buf, sizeof(buf), 0 );
|
||||
ok( ret == sizeof(buf), "got %d, error %u, i %u.\n", ret, WSAGetLastError(), i );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void test_UDP(void)
|
||||
{
|
||||
/* This function tests UDP sendto() and recvfrom(). UDP is unreliable, so it is
|
||||
|
@ -3117,6 +3140,9 @@ static void test_UDP(void)
|
|||
int ss, i, n_recv, n_sent, ret;
|
||||
struct sockaddr_in addr;
|
||||
int sock;
|
||||
struct send_udp_thread_param udp_thread_param;
|
||||
HANDLE thread;
|
||||
|
||||
|
||||
memset (buf,0,sizeof(buf));
|
||||
for ( i = NUM_UDP_PEERS - 1; i >= 0; i-- ) {
|
||||
|
@ -3174,6 +3200,22 @@ static void test_UDP(void)
|
|||
ok( ret == sizeof(buf), "got %d, error %u.\n", ret, WSAGetLastError() );
|
||||
}
|
||||
|
||||
/* Test sending packets in parallel (mostly a regression test for Wine async handling race conditions). */
|
||||
set_blocking( sock, FALSE );
|
||||
|
||||
udp_thread_param.sock = sock;
|
||||
udp_thread_param.start_event = CreateEventW( NULL, FALSE, FALSE, NULL );
|
||||
thread = CreateThread( NULL, 0, send_udp_thread, &udp_thread_param, 0, NULL );
|
||||
SetEvent( udp_thread_param.start_event );
|
||||
for (i = 0; i < 256; ++i)
|
||||
{
|
||||
ret = send( sock, buf, sizeof(buf), 0 );
|
||||
ok( ret == sizeof(buf), "got %d, error %u, i %u.\n", ret, WSAGetLastError(), i );
|
||||
}
|
||||
WaitForSingleObject( thread, INFINITE );
|
||||
CloseHandle( thread );
|
||||
CloseHandle( udp_thread_param.start_event );
|
||||
|
||||
closesocket(sock);
|
||||
}
|
||||
|
||||
|
|
|
@ -551,6 +551,16 @@ void async_set_result( struct object *obj, unsigned int status, apc_param_t tota
|
|||
}
|
||||
}
|
||||
|
||||
int async_queue_has_waiting_asyncs( struct async_queue *queue )
|
||||
{
|
||||
struct async *async;
|
||||
|
||||
LIST_FOR_EACH_ENTRY( async, &queue->queue, struct async, queue_entry )
|
||||
if (!async->unknown_status) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check if an async operation is waiting to be alerted */
|
||||
int async_waiting( struct async_queue *queue )
|
||||
{
|
||||
|
|
|
@ -237,6 +237,7 @@ extern void set_async_pending( struct async *async );
|
|||
extern void async_set_initial_status( struct async *async, unsigned int status );
|
||||
extern void async_wake_obj( struct async *async );
|
||||
extern int async_waiting( struct async_queue *queue );
|
||||
extern int async_queue_has_waiting_asyncs( struct async_queue *queue );
|
||||
extern void async_terminate( struct async *async, unsigned int status );
|
||||
extern void async_request_complete( struct async *async, unsigned int status, data_size_t result,
|
||||
data_size_t out_size, void *out_data );
|
||||
|
|
|
@ -3945,7 +3945,7 @@ DECL_HANDLER(send_socket)
|
|||
|
||||
if (bind_errno) status = sock_get_ntstatus( bind_errno );
|
||||
else if (sock->wr_shutdown) status = STATUS_PIPE_DISCONNECTED;
|
||||
else if (!async_queued( &sock->write_q ))
|
||||
else if (!async_queue_has_waiting_asyncs( &sock->write_q ))
|
||||
{
|
||||
/* If write_q is not empty, we cannot really tell if the already queued
|
||||
* asyncs will not consume all available space; if there's no space
|
||||
|
|
Loading…
Add table
Reference in a new issue