From 08867f7149f82446f8df9e3ebfa85563db5adbf2 Mon Sep 17 00:00:00 2001 From: Martin Wilck <Martin.Wilck@fujitsu-siemens.com> Date: Sun, 14 Apr 2002 19:34:57 +0000 Subject: [PATCH] - Need a "cleanup" method. - calling the "call_completion" method unconditionally in finish_async (introduced by me) was wrong, because the thread may never be in an alertable wait state -> call it only if user completion function is present. - We need two constant "ops" objects, one with and one without call_completion method (the event field may NOT be used to determine whether the completion must be called or not). --- dlls/kernel/comm.c | 9 ++++---- files/file.c | 57 ++++++++++++++++++++++++++++++++++------------ include/async.h | 13 +++++++++-- 3 files changed, 58 insertions(+), 21 deletions(-) diff --git a/dlls/kernel/comm.c b/dlls/kernel/comm.c index 53da53cf95f..ac477e93403 100644 --- a/dlls/kernel/comm.c +++ b/dlls/kernel/comm.c @@ -99,14 +99,15 @@ WINE_DEFAULT_DEBUG_CHANNEL(comm); static DWORD commio_get_async_status (const async_private *ovp); static DWORD commio_get_async_count (const async_private *ovp); static void commio_set_async_status (async_private *ovp, const DWORD status); -static void CALLBACK commio_call_completion_func (ULONG_PTR data); +static void commio_async_cleanup (async_private *ovp); static async_ops commio_async_ops = { commio_get_async_status, /* get_status */ commio_set_async_status, /* set_status */ commio_get_async_count, /* get_count */ - commio_call_completion_func /* call_completion */ + NULL, /* call_completion */ + commio_async_cleanup /* cleanup */ }; typedef struct async_commio @@ -131,9 +132,9 @@ static DWORD commio_get_async_count (const struct async_private *ovp) return 0; } -static void CALLBACK commio_call_completion_func (ULONG_PTR data) +static void commio_async_cleanup (async_private *ovp) { - HeapFree(GetProcessHeap(), 0, (void*) data); + HeapFree(GetProcessHeap(), 0, ovp ); } /***********************************************************************/ diff --git a/files/file.c b/files/file.c index d698bf676cb..582ef8f39f8 100644 --- a/files/file.c +++ b/files/file.c @@ -88,13 +88,24 @@ static DWORD fileio_get_async_status (const async_private *ovp); static DWORD fileio_get_async_count (const async_private *ovp); static void fileio_set_async_status (async_private *ovp, const DWORD status); static void CALLBACK fileio_call_completion_func (ULONG_PTR data); +static void fileio_async_cleanup (async_private *ovp); static async_ops fileio_async_ops = { fileio_get_async_status, /* get_status */ fileio_set_async_status, /* set_status */ fileio_get_async_count, /* get_count */ - fileio_call_completion_func /* call_completion */ + fileio_call_completion_func, /* call_completion */ + fileio_async_cleanup /* cleanup */ +}; + +static async_ops fileio_nocomp_async_ops = +{ + fileio_get_async_status, /* get_status */ + fileio_set_async_status, /* set_status */ + fileio_get_async_count, /* get_count */ + NULL, /* call_completion */ + fileio_async_cleanup /* cleanup */ }; typedef struct async_fileio @@ -128,12 +139,16 @@ static void CALLBACK fileio_call_completion_func (ULONG_PTR data) async_fileio *ovp = (async_fileio*) data; TRACE ("data: %p\n", ovp); - if (ovp->completion_func) - ovp->completion_func(ovp->lpOverlapped->Internal, - ovp->lpOverlapped->InternalHigh, - ovp->lpOverlapped); + ovp->completion_func( ovp->lpOverlapped->Internal, + ovp->lpOverlapped->InternalHigh, + ovp->lpOverlapped ); - HeapFree(GetProcessHeap(), 0, ovp); + fileio_async_cleanup ( &ovp->async ); +} + +static void fileio_async_cleanup ( struct async_private *ovp ) +{ + HeapFree ( GetProcessHeap(), 0, ovp ); } /*********************************************************************** @@ -1478,6 +1493,8 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, { async_fileio *ovp; int fd; + int flags; + enum fd_type type; TRACE("file %d to buf %p num %ld %p func %p\n", hFile, buffer, bytesToRead, overlapped, lpCompletionRoutine); @@ -1489,10 +1506,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, return FALSE; } - fd = FILE_GetUnixHandle( hFile, GENERIC_READ ); - if(fd<0) + fd = FILE_GetUnixHandleType ( hFile, GENERIC_READ, &type, &flags); + if ( fd < 0 ) { - TRACE("Couldn't get FD\n"); + WARN ( "Couldn't get FD\n" ); + SetLastError ( ERROR_INVALID_PARAMETER ); return FALSE; } @@ -1501,11 +1519,10 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, { TRACE("HeapAlloc Failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); - close(fd); - return FALSE; + goto error; } - ovp->async.ops = &fileio_async_ops; + ovp->async.ops = ( lpCompletionRoutine ? &fileio_async_ops : &fileio_nocomp_async_ops ); ovp->async.handle = hFile; ovp->async.fd = fd; ovp->async.type = ASYNC_TYPE_READ; @@ -1517,6 +1534,11 @@ static BOOL FILE_ReadFileEx(HANDLE hFile, LPVOID buffer, DWORD bytesToRead, ovp->buffer = buffer; return !register_new_async (&ovp->async); + +error: + close (fd); + return FALSE; + } /*********************************************************************** @@ -1710,6 +1732,8 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, { async_fileio *ovp; int fd; + int flags; + enum fd_type type; TRACE("file %d to buf %p num %ld %p func %p stub\n", hFile, buffer, bytesToWrite, overlapped, lpCompletionRoutine); @@ -1720,7 +1744,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, return FALSE; } - fd = FILE_GetUnixHandle( hFile, GENERIC_WRITE ); + fd = FILE_GetUnixHandleType ( hFile, GENERIC_WRITE, &type, &flags ); if ( fd < 0 ) { TRACE( "Couldn't get FD\n" ); @@ -1732,8 +1756,7 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, { TRACE("HeapAlloc Failed\n"); SetLastError(ERROR_NOT_ENOUGH_MEMORY); - close (fd); - return FALSE; + goto error; } ovp->async.ops = &fileio_async_ops; @@ -1748,6 +1771,10 @@ static BOOL FILE_WriteFileEx(HANDLE hFile, LPCVOID buffer, DWORD bytesToWrite, ovp->completion_func = lpCompletionRoutine; return !register_new_async (&ovp->async); + +error: + close (fd); + return FALSE; } /*********************************************************************** diff --git a/include/async.h b/include/async.h index 26774d38dfb..6b6359a41a8 100644 --- a/include/async.h +++ b/include/async.h @@ -35,6 +35,7 @@ typedef void CALLBACK (*async_call_completion_func)(ULONG_PTR data); typedef DWORD (*async_get_status)(const struct async_private *ovp); typedef DWORD (*async_get_count)(const struct async_private *ovp); typedef void (*async_set_status)(struct async_private *ovp, const DWORD status); +typedef void (*async_cleanup)(struct async_private *ovp); typedef struct async_ops { @@ -42,6 +43,7 @@ typedef struct async_ops async_set_status set_status; async_get_count get_count; async_call_completion_func call_completion; + async_cleanup cleanup; } async_ops; typedef struct async_private @@ -74,7 +76,10 @@ inline static void finish_async( async_private *ovp ) if( ovp->event != INVALID_HANDLE_VALUE ) NtSetEvent( ovp->event, NULL ); - QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp ); + if ( ovp->ops->call_completion ) + QueueUserAPC( ovp->ops->call_completion, GetCurrentThread(), (ULONG_PTR)ovp ); + else + ovp->ops->cleanup ( ovp ); } inline static BOOL __register_async( async_private *ovp, const DWORD status ) @@ -92,7 +97,11 @@ inline static BOOL __register_async( async_private *ovp, const DWORD status ) } SERVER_END_REQ; - if ( ret ) ovp->ops->set_status ( ovp, GetLastError() ); + if ( ret ) { + SetLastError( RtlNtStatusToDosError(ret) ); + ovp->ops->set_status ( ovp, ret ); + } + if ( ovp->ops->get_status (ovp) != STATUS_PENDING ) finish_async (ovp); -- GitLab