From 589ce2bb8d1b3c199d71dac7f07d98f49b6eae09 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 26 Mar 2007 19:13:21 +0200 Subject: [PATCH] server: Always return STATUS_PENDING when an async I/O operation has been queued. --- dlls/ntdll/file.c | 13 ++++++------- dlls/ws2_32/socket.c | 20 ++++++++------------ server/fd.c | 5 ++--- server/serial.c | 1 + server/sock.c | 1 + 5 files changed, 18 insertions(+), 22 deletions(-) diff --git a/dlls/ntdll/file.c b/dlls/ntdll/file.c index 45786b02d16..6873e0e77ae 100644 --- a/dlls/ntdll/file.c +++ b/dlls/ntdll/file.c @@ -282,14 +282,13 @@ static ULONG fileio_queue_async(async_fileio* fileio, IO_STATUS_BLOCK* iosb, } SERVER_END_REQ; - if ( status ) iosb->u.Status = status; - if ( iosb->u.Status != STATUS_PENDING ) + if (status != STATUS_PENDING) { + iosb->u.Status = status; (apc)( fileio, iosb, iosb->u.Status ); - return iosb->u.Status; } - NtCurrentTeb()->num_async_io++; - return STATUS_SUCCESS; + else NtCurrentTeb()->num_async_io++; + return status; } /*********************************************************************** @@ -531,7 +530,7 @@ NTSTATUS WINAPI NtReadFile(HANDLE hFile, HANDLE hEvent, io_status->u.Status = STATUS_PENDING; ret = fileio_queue_async(fileio, io_status, TRUE); - if (ret != STATUS_SUCCESS) + if (ret != STATUS_PENDING) { if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent); return ret; @@ -762,7 +761,7 @@ NTSTATUS WINAPI NtWriteFile(HANDLE hFile, HANDLE hEvent, io_status->Information = 0; io_status->u.Status = STATUS_PENDING; ret = fileio_queue_async(fileio, io_status, FALSE); - if (ret != STATUS_SUCCESS) + if (ret != STATUS_PENDING) { if (flags & FD_FLAG_TIMEOUT) NtClose(hEvent); return ret; diff --git a/dlls/ws2_32/socket.c b/dlls/ws2_32/socket.c index 4ad025ecf91..ce57f7d7801 100644 --- a/dlls/ws2_32/socket.c +++ b/dlls/ws2_32/socket.c @@ -1150,6 +1150,7 @@ static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb) default: FIXME("Unknown internal mode (%d)\n", wsa->mode); return STATUS_INVALID_PARAMETER; } + iosb->u.Status = STATUS_PENDING; SERVER_START_REQ( register_async ) { req->handle = wsa->hSocket; @@ -1163,18 +1164,13 @@ static ULONG ws2_queue_async(struct ws2_async* wsa, IO_STATUS_BLOCK* iosb) } SERVER_END_REQ; - if ( status ) iosb->u.Status = status; - if ( iosb->u.Status != STATUS_PENDING ) + if (status != STATUS_PENDING) { - /* Note: we get here a non zero status when we couldn't queue the async - * in the server. Therefore, we simply terminate the async. - */ - status = iosb->u.Status; + iosb->u.Status = status; ws2_async_terminate(wsa, iosb); - return status; } - NtCurrentTeb()->num_async_io++; - return STATUS_SUCCESS; + else NtCurrentTeb()->num_async_io++; + return status; } /*********************************************************************** @@ -1500,7 +1496,7 @@ static int WS2_register_async_shutdown( SOCKET s, enum ws2_mode mode ) /* Hack: this will cause ws2_async_terminate() to free the overlapped structure */ wsa->user_overlapped = NULL; - if ( (ret = ws2_queue_async( wsa, iosb )) ) + if ((ret = ws2_queue_async( wsa, iosb )) != STATUS_PENDING) { err = NtStatusToWSAError( ret ); goto out; @@ -2843,7 +2839,7 @@ INT WINAPI WSASendTo( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, goto err_free; } - if ( ( ret = ws2_queue_async( wsa, iosb ) ) ) + if ((ret = ws2_queue_async( wsa, iosb )) != STATUS_PENDING) { err = NtStatusToWSAError( ret ); @@ -4349,7 +4345,7 @@ INT WINAPI WSARecvFrom( SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, goto err_free; } - if ( ( ret = ws2_queue_async( wsa, iosb )) ) + if ((ret = ws2_queue_async( wsa, iosb )) != STATUS_PENDING) { err = NtStatusToWSAError( ret ); diff --git a/server/fd.c b/server/fd.c index fba69074953..bf5f2e048d9 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1742,6 +1742,7 @@ void fd_queue_async_timeout( struct fd *fd, const async_data_t *data, int type, } if (!create_async( current, timeout, queue, data )) return; + set_error( STATUS_PENDING ); /* Check if the new pending request can be served immediately */ events = check_fd_events( fd, fd->fd_ops->get_poll_events( fd ) ); @@ -1937,9 +1938,7 @@ DECL_HANDLER(register_async) * 3. Carry out any operations necessary to adjust the object's poll events * Usually: set_elect_events (obj, obj->ops->get_poll_events()). * 4. When the async request is triggered, then send back (with a proper APC) - * the trigger (STATUS_ALERTED) to the thread that posted the request. - * async_destroy() is to be called: it will both notify the sender about - * the trigger and destroy the request by itself + * the trigger (STATUS_ALERTED) to the thread that posted the request. * See also the implementations in file.c, serial.c, and sock.c. */ diff --git a/server/serial.c b/server/serial.c index d459426a517..7b92fac23aa 100644 --- a/server/serial.c +++ b/server/serial.c @@ -273,6 +273,7 @@ static void serial_queue_async( struct fd *fd, const async_data_t *data, int typ add_timeout( &when, timeout ); if (!create_async( current, timeout ? &when : NULL, queue, data )) return; + set_error( STATUS_PENDING ); /* Check if the new pending request can be served immediately */ events = check_fd_events( fd, serial_get_poll_events( fd ) ); diff --git a/server/sock.c b/server/sock.c index f1b7255122a..009d37eade7 100644 --- a/server/sock.c +++ b/server/sock.c @@ -545,6 +545,7 @@ static void sock_queue_async( struct fd *fd, const async_data_t *data, int type, else { if (!create_async( current, NULL, queue, data )) return; + set_error( STATUS_PENDING ); } pollev = sock_reselect( sock );