PATCH: async-immediate.diff (1 in series)

Martin Wilck Martin.Wilck at fujitsu-siemens.com
Fri Apr 12 10:17:01 CDT 2002


PATCH: async-immediate.diff

(Resubmission of
http://www.winehq.com/hypermail/wine-patches/2002/04/0021.html)

This patch uses a more elegant and (IMO) more wine-ish method to check for
possible immediate completion of asynchronous IO requests in ReadFile() and
WriteFile().

The implementation in current CVS is wrong for 2 reasons:

1. The overlapped event is not set, nor the completion routine called,
   if immediate completion succeeds. This breaks apps that do not check
   for immediate success.
2. If there are async requests currently in the queue, immediate completion
   will bypass the request ordering. This will lead to data corruption
   on FIFO-type files.

The patch fixes this.

Patch against: Wine CVS 2002-04-12

Test status: Compiles (no errors/warnings).
        Tested for regular file IO (ok).
        The 2002-01-15 patch has been tested for 16-bit serial IO by Lawson Whitney (ok).

Modified Files:
        files           : file.c

Log message:
        Martin Wilck <Martin.Wilck at Fujitsu-Siemens.com>
        GetOverlappedResult(): Return ERROR_IO_INCOMPLETE if IO still pending (MSDN docs)
        ReadFile() / WriteFile(): Use GetOverlappedResult() to check for immediate completion.


diff -ruNX ignore TMP/wine/files/file.c MW/wine/files/file.c
--- TMP/wine/files/file.c	Tue Apr  9 13:20:25 2002
+++ MW/wine/files/file.c	Tue Apr  9 13:25:25 2002
@@ -1395,7 +1395,8 @@
     if(lpTransferred)
         *lpTransferred = lpOverlapped->InternalHigh;

-    SetLastError(lpOverlapped->Internal);
+    SetLastError ( lpOverlapped->Internal == STATUS_PENDING ?
+                   ERROR_IO_INCOMPLETE : lpOverlapped->Internal );

     return (r==WAIT_OBJECT_0);
 }
@@ -1576,41 +1577,21 @@
             SetLastError(ERROR_INVALID_PARAMETER);
             return FALSE;
         }
-
-        /* see if we can read some data already (this shouldn't block) */
-        result = pread( unix_handle, buffer, bytesToRead, OVERLAPPED_OFFSET(overlapped) );
-        if ((result < 0) && (errno == ESPIPE))
-            result = read( unix_handle, buffer, bytesToRead );
-        close(unix_handle);
-
-        if(result<0)
-        {
-            if( (errno!=EAGAIN) && (errno!=EINTR) &&
-                ((errno != EFAULT) || IsBadWritePtr( buffer, bytesToRead )) )
-            {
-                FILE_SetDosError();
-                return FALSE;
-            }
-            else
-                result = 0;
-        }

-        /* if we read enough to keep the app happy, then return now */
-        if(result>=bytesToRead)
-        {
-            *bytesRead = result;
-            return TRUE;
-        }
-
-        /* at last resort, do an overlapped read */
-        overlapped->InternalHigh = result;
+        close(unix_handle);
+        overlapped->InternalHigh = 0;

         if(!FILE_ReadFileEx(hFile, buffer, bytesToRead, overlapped, NULL, overlapped->hEvent))
             return FALSE;

-        /* fail on return, with ERROR_IO_PENDING */
-        SetLastError(ERROR_IO_PENDING);
-        return FALSE;
+        if ( !GetOverlappedResult (hFile, overlapped, bytesRead, FALSE) )
+        {
+            if ( GetLastError() == ERROR_IO_INCOMPLETE )
+                SetLastError ( ERROR_IO_PENDING );
+            return FALSE;
+        }
+
+        return TRUE;
     }
     if (flags & FD_FLAG_TIMEOUT)
     {
@@ -1790,43 +1771,20 @@
             return FALSE;
         }

-        /* see if we can write some data already (this shouldn't block) */
-
-        result = pwrite( unix_handle, buffer, bytesToWrite, OVERLAPPED_OFFSET (overlapped) );
-        if ((result < 0) && (errno == ESPIPE))
-            result = write( unix_handle, buffer, bytesToWrite );
-
         close(unix_handle);
+        overlapped->InternalHigh = 0;

-        if(result<0)
-        {
-            if( (errno!=EAGAIN) && (errno!=EINTR) &&
-                ((errno != EFAULT) || IsBadReadPtr( buffer, bytesToWrite )) )
-            {
-                FILE_SetDosError();
-                return FALSE;
-            }
-            else
-                result = 0;
-        }
+        if(!FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, NULL, overlapped->hEvent))
+            return FALSE;

-        /* if we wrote enough to keep the app happy, then return now */
-        if(result>=bytesToWrite)
+        if ( !GetOverlappedResult (hFile, overlapped, bytesWritten, FALSE) )
         {
-            *bytesWritten = result;
-            return TRUE;
-        }
-
-        /* at last resort, do an overlapped read */
-        overlapped->Internal     = STATUS_PENDING;
-        overlapped->InternalHigh = result;
-
-        if(!FILE_WriteFileEx(hFile, buffer, bytesToWrite, overlapped, NULL, overlapped->hEvent))
+            if ( GetLastError() == ERROR_IO_INCOMPLETE )
+                SetLastError ( ERROR_IO_PENDING );
             return FALSE;
+        }

-        /* fail on return, with ERROR_IO_PENDING */
-        SetLastError(ERROR_IO_PENDING);
-        return FALSE;
+        return TRUE;
     }

     switch(type)





More information about the wine-devel mailing list