From 3afbee521845443e1a757a1b0afbd6d0abccbd63 Mon Sep 17 00:00:00 2001 From: Andrey Turkin Date: Mon, 17 Dec 2007 22:06:17 +0300 Subject: [PATCH] server: Store I/O completion information in async structure. This is to allow completions to be sent on handle close. Also this can be helpful for AcceptEx/TransmitFile implementation. --- dlls/ntdll/tests/file.c | 14 +++++++++++++- server/async.c | 12 ++++++------ server/fd.c | 10 +++++----- server/file.h | 2 +- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 4e1833c91a..8d2ffc35f1 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -566,9 +566,21 @@ static void test_iocp_fileio(HANDLE h) ok( U(ioSb).Status == STATUS_SUCCESS, "Invalid ioSb.Status: %x\n", U(ioSb).Status); ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); } + + ReadFile( hPipeSrv, buf, sizeof(buf), &read, &o); + CloseHandle( hPipeSrv ); + count = get_pending_msgs(h); + ok( count == 1, "Unexpected msg count: %ld\n", count ); + if (get_msg(h)) + { + ok( completionKey == CKEY_SECOND, "Invalid completion key: %lx\n", completionKey ); + ok( ioSb.Information == 0, "Invalid ioSb.Information: %ld\n", ioSb.Information ); + /* wine sends wrong status here */ + todo_wine ok( U(ioSb).Status == STATUS_PIPE_BROKEN, "Invalid ioSb.Status: %x\n", U(ioSb).Status); + ok( completionValue == (ULONG_PTR)&o, "Invalid completion value: %lx\n", completionValue ); + } } - CloseHandle( hPipeSrv ); CloseHandle( hPipeClt ); } diff --git a/server/async.c b/server/async.c index ae586368d1..ff5f7a67ab 100644 --- a/server/async.c +++ b/server/async.c @@ -42,6 +42,8 @@ struct async struct timeout_user *timeout; unsigned int timeout_status; /* status to report upon timeout */ struct event *event; + struct completion *completion; + unsigned long comp_key; async_data_t data; /* data for async I/O call */ }; @@ -121,6 +123,7 @@ static void async_destroy( struct object *obj ) if (async->timeout) remove_timeout_user( async->timeout ); if (async->event) release_object( async->event ); + if (async->completion) release_object( async->completion ); release_object( async->queue ); release_object( async->thread ); } @@ -146,10 +149,6 @@ void async_terminate( struct async *async, unsigned int status ) return; } - /* send error completion event */ - if (status != STATUS_ALERTED && async->data.cvalue && async->queue->fd) - fd_add_completion( async->queue->fd, async->data.cvalue, status, 0 ); - memset( &data, 0, sizeof(data) ); data.type = APC_ASYNC_IO; data.async_io.func = async->data.callback; @@ -214,6 +213,7 @@ struct async *create_async( struct thread *thread, struct async_queue *queue, co async->data = *data; async->timeout = NULL; async->queue = (struct async_queue *)grab_object( queue ); + fd_assign_completion( queue->fd, &async->completion, &async->comp_key ); list_add_tail( &queue->queue, &async->queue_entry ); grab_object( async ); @@ -257,8 +257,8 @@ void async_set_result( struct object *obj, unsigned int status, unsigned long to if (async->timeout) remove_timeout_user( async->timeout ); async->timeout = NULL; async->status = status; - if (async->data.cvalue && async->queue->fd) - fd_add_completion( async->queue->fd, async->data.cvalue, status, total ); + if (async->completion && async->data.cvalue) + add_completion( async->completion, async->comp_key, async->data.cvalue, status, total ); if (async->data.apc) { apc_call_t data; diff --git a/server/fd.c b/server/fd.c index 95a0520787..c7f20d5259 100644 --- a/server/fd.c +++ b/server/fd.c @@ -1922,11 +1922,10 @@ static struct fd *get_handle_fd_obj( struct process *process, obj_handle_t handl return fd; } -/* add a completion result to a completion queue attached to the fd */ -void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information ) +void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key ) { - if (fd->completion) - add_completion( fd->completion, fd->comp_key, cvalue, status, information ); + *p_key = fd->comp_key; + *p_port = fd->completion ? (struct completion *)grab_object( fd->completion ) : NULL; } /* flush a file buffers */ @@ -2066,7 +2065,8 @@ DECL_HANDLER(add_fd_completion) struct fd *fd = get_handle_fd_obj( current->process, req->handle, 0 ); if (fd) { - fd_add_completion( fd, req->cvalue, req->status, req->information ); + if (fd->completion) + add_completion( fd->completion, fd->comp_key, req->cvalue, req->status, req->information ); release_object( fd ); } } diff --git a/server/file.h b/server/file.h index e444007da1..26d170263b 100644 --- a/server/file.h +++ b/server/file.h @@ -139,7 +139,7 @@ extern void async_set_result( struct object *obj, unsigned int status, unsigned extern int async_waiting( struct async_queue *queue ); extern void async_terminate( struct async *async, unsigned int status ); extern void async_wake_up( struct async_queue *queue, unsigned int status ); -extern void fd_add_completion( struct fd *fd, unsigned long cvalue, unsigned int status, unsigned long information ); +extern void fd_assign_completion( struct fd *fd, struct completion **p_port, unsigned long *p_key ); /* access rights that require Unix read permission */ #define FILE_UNIX_READ_ACCESS (FILE_READ_DATA|FILE_READ_ATTRIBUTES|FILE_READ_EA) -- 2.32.0.93.g670b81a890