Signed-off-by: Paul Gofman pgofman@codeweavers.com --- Similar to WinHttpWebSocketReceive() but requires a separate variable because control frame send may be queued from read operation for pong. It is not quite straightforward to add to test as most of the time the send is executed synchronously. I tested that manually however and repeated sends without wait in between trigger this error on Windows.
I am not aware of any app depending on this behaviour but it simplifies the synchronization for the next patch.
dlls/winhttp/request.c | 16 +++++++++++++++- dlls/winhttp/winhttp_private.h | 1 + 2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index d0732952e11..de011060236 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -3349,6 +3349,7 @@ static void CALLBACK task_socket_send( TP_CALLBACK_INSTANCE *instance, void *ctx else ret = socket_send( s->socket, s->type, s->buf, s->len, NULL );
send_io_complete( &s->socket->hdr ); + InterlockedExchange( &s->socket->pending_noncontrol_send, 0 ); socket_send_complete( s->socket, ret, s->type, s->len );
release_object( &s->socket->hdr ); @@ -3386,8 +3387,16 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_ BOOL async_send, complete_async = FALSE; struct socket_send *s;
+ if (InterlockedCompareExchange( &socket->pending_noncontrol_send, 1, 0 )) + { + WARN( "Previous send is still queued.\n" ); + release_object( &socket->hdr ); + return ERROR_INVALID_OPERATION; + } + if (!(s = malloc( sizeof(*s) ))) { + InterlockedExchange( &socket->pending_noncontrol_send, 0 ); release_object( &socket->hdr ); return ERROR_OUTOFMEMORY; } @@ -3417,11 +3426,16 @@ DWORD WINAPI WinHttpWebSocketSend( HINTERNET hsocket, WINHTTP_WEB_SOCKET_BUFFER_ if ((ret = queue_task( &socket->send_q, task_socket_send, s ))) { InterlockedDecrement( &socket->hdr.pending_sends ); + InterlockedExchange( &socket->pending_noncontrol_send, 0 ); release_object( &socket->hdr ); free( s ); } } - else InterlockedDecrement( &socket->hdr.pending_sends ); + else + { + InterlockedDecrement( &socket->hdr.pending_sends ); + InterlockedExchange( &socket->pending_noncontrol_send, 0 ); + } ReleaseSRWLockExclusive( &socket->send_lock ); if (!async_send) { diff --git a/dlls/winhttp/winhttp_private.h b/dlls/winhttp/winhttp_private.h index 732f0afaa88..cf6655f561f 100644 --- a/dlls/winhttp/winhttp_private.h +++ b/dlls/winhttp/winhttp_private.h @@ -260,6 +260,7 @@ struct socket unsigned int bytes_in_send_frame_buffer; unsigned int client_buffer_offset; SRWLOCK send_lock; + volatile LONG pending_noncontrol_send; };
struct send_request