mirror of
https://github.com/wine-mirror/wine
synced 2024-07-01 07:14:31 +00:00
server: Check if we have waiting asyncs in (send_socket) before enforcing blocking send.
This commit is contained in:
parent
294efcdf44
commit
aac0998262
|
@ -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)
|
static void test_UDP(void)
|
||||||
{
|
{
|
||||||
/* This function tests UDP sendto() and recvfrom(). UDP is unreliable, so it is
|
/* 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;
|
int ss, i, n_recv, n_sent, ret;
|
||||||
struct sockaddr_in addr;
|
struct sockaddr_in addr;
|
||||||
int sock;
|
int sock;
|
||||||
|
struct send_udp_thread_param udp_thread_param;
|
||||||
|
HANDLE thread;
|
||||||
|
|
||||||
|
|
||||||
memset (buf,0,sizeof(buf));
|
memset (buf,0,sizeof(buf));
|
||||||
for ( i = NUM_UDP_PEERS - 1; i >= 0; i-- ) {
|
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() );
|
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);
|
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 */
|
/* check if an async operation is waiting to be alerted */
|
||||||
int async_waiting( struct async_queue *queue )
|
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_set_initial_status( struct async *async, unsigned int status );
|
||||||
extern void async_wake_obj( struct async *async );
|
extern void async_wake_obj( struct async *async );
|
||||||
extern int async_waiting( struct async_queue *queue );
|
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_terminate( struct async *async, unsigned int status );
|
||||||
extern void async_request_complete( struct async *async, unsigned int status, data_size_t result,
|
extern void async_request_complete( struct async *async, unsigned int status, data_size_t result,
|
||||||
data_size_t out_size, void *out_data );
|
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 );
|
if (bind_errno) status = sock_get_ntstatus( bind_errno );
|
||||||
else if (sock->wr_shutdown) status = STATUS_PIPE_DISCONNECTED;
|
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
|
/* 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
|
* asyncs will not consume all available space; if there's no space
|
||||||
|
|
Loading…
Reference in New Issue
Block a user