Retry in FileRead and FileWrite if Windows returns ERROR_NO_SYSTEM_RESOURCES.
authorTom Lane
Thu, 1 Dec 2005 20:24:18 +0000 (20:24 +0000)
committerTom Lane
Thu, 1 Dec 2005 20:24:18 +0000 (20:24 +0000)
Also add a retry for Unixen returning EINTR, which hasn't been reported
as an issue but at least theoretically could be.  Patch by Qingqing Zhou,
some minor adjustments by me.

src/backend/storage/file/fd.c

index 2ab14976b8393e3c649a96010fa74c1038551bee..f54e164f5f95bb1910ce411e5ac92a2c5a40f10c 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.122 2005/11/22 18:17:20 momjian Exp $
+ *   $PostgreSQL: pgsql/src/backend/storage/file/fd.c,v 1.123 2005/12/01 20:24:18 tgl Exp $
  *
  * NOTES:
  *
@@ -1009,11 +1009,41 @@ FileRead(File file, char *buffer, int amount)
    if (returnCode < 0)
        return returnCode;
 
+retry:
    returnCode = read(VfdCache[file].fd, buffer, amount);
-   if (returnCode > 0)
+
+   if (returnCode >= 0)
        VfdCache[file].seekPos += returnCode;
    else
+   {
+       /*
+        * Windows may run out of kernel buffers and return "Insufficient
+        * system resources" error.  Wait a bit and retry to solve it.
+        *
+        * It is rumored that EINTR is also possible on some Unix filesystems,
+        * in which case immediate retry is indicated.
+        */
+#ifdef WIN32
+       DWORD error = GetLastError();
+
+       switch (error)
+       {
+           case ERROR_NO_SYSTEM_RESOURCES:
+               pg_usleep(1000L);
+               errno = EINTR;
+               break;
+           default:
+               _dosmaperr(error);
+               break;
+       }
+#endif
+       /* OK to retry if interrupted */
+       if (errno == EINTR)
+           goto retry;
+
+       /* Trouble, so assume we don't know the file position anymore */
        VfdCache[file].seekPos = FileUnknownPos;
+   }
 
    return returnCode;
 }
@@ -1033,6 +1063,7 @@ FileWrite(File file, char *buffer, int amount)
    if (returnCode < 0)
        return returnCode;
 
+retry:
    errno = 0;
    returnCode = write(VfdCache[file].fd, buffer, amount);
 
@@ -1040,10 +1071,34 @@ FileWrite(File file, char *buffer, int amount)
    if (returnCode != amount && errno == 0)
        errno = ENOSPC;
 
-   if (returnCode > 0)
+   if (returnCode >= 0)
        VfdCache[file].seekPos += returnCode;
    else
+   {
+       /*
+        * See comments in FileRead()
+        */
+#ifdef WIN32
+       DWORD error = GetLastError();
+
+       switch (error)
+       {
+           case ERROR_NO_SYSTEM_RESOURCES:
+               pg_usleep(1000L);
+               errno = EINTR;
+               break;
+           default:
+               _dosmaperr(error);
+               break;
+       }
+#endif
+       /* OK to retry if interrupted */
+       if (errno == EINTR)
+           goto retry;
+
+       /* Trouble, so assume we don't know the file position anymore */
        VfdCache[file].seekPos = FileUnknownPos;
+   }
 
    return returnCode;
 }