I come up with a patch to fix server-side problem. The basic idea is to
convert ERROR_NO_SYSTEM_RESOURCES to EINTR and add code to do retry unless
a new error encountered or successfully done. I tweak the FileRead() logic
on "returnCode <= 0" a little bit by separating it to "<0" and "==0"
parts. This is because if our read passed EOF, read() will not set errno
which may cause a dead loop if a previous read() is interrupted.
For windows, I set a one second waiting time - this should be ok since the
problem is very rare. If the error is permenate, you can always SIGINT the
process since the waiting is done by pg_usleep().
Regards,
Qingqing
---
Index: src/backend/storage/file/fd.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/file/fd.c,v
retrieving revision 1.122
diff -c -r1.122 fd.c
*** src/backend/storage/file/fd.c 22 Nov 2005 18:17:20 -0000 1.122
--- src/backend/storage/file/fd.c 1 Dec 2005 01:09:59 -0000
***************
*** 1009,1019 **** if (returnCode < 0) return returnCode;
! returnCode = read(VfdCache[file].fd, buffer, amount);
! if (returnCode > 0)
! VfdCache[file].seekPos += returnCode;
! else
! VfdCache[file].seekPos = FileUnknownPos;
return returnCode; }
--- 1009,1052 ---- if (returnCode < 0) return returnCode;
! for (;;)
! {
! returnCode = read(VfdCache[file].fd, buffer, amount);
!
! if (returnCode > 0)
! VfdCache[file].seekPos += returnCode;
! else if (returnCode == 0)
! VfdCache[file].seekPos = FileUnknownPos;
! else
! {
! #ifdef WIN32
! DWORD error = GetLastError();
!
! switch (error)
! {
! /*
! * Since we are using buffered IO now, so windows may run
! * out of kernel buffer and return a "Insufficient system
! * resources" error. Retry to solve it.
! */
! case ERROR_NO_SYSTEM_RESOURCES:
! pg_usleep(1000);
! errno = EINTR;
! break;
! default:
! _dosmaperr(error);
! Assert(errno != EINTR);
! }
! #endif
! /* Ok if interrupted and retry */
! if (errno == EINTR)
! continue;
!
! VfdCache[file].seekPos = FileUnknownPos;
! }
!
! break;
! }
return returnCode; }
***************
*** 1033,1049 **** if (returnCode < 0) return returnCode;
! errno = 0;
! returnCode = write(VfdCache[file].fd, buffer, amount);
! /* if write didn't set errno, assume problem is no disk space */
! if (returnCode != amount && errno == 0)
! errno = ENOSPC;
! if (returnCode > 0)
! VfdCache[file].seekPos += returnCode;
! else
! VfdCache[file].seekPos = FileUnknownPos;
return returnCode; }
--- 1066,1108 ---- if (returnCode < 0) return returnCode;
! for (;;)
! {
! errno = 0;
! returnCode = write(VfdCache[file].fd, buffer, amount);
! /* if write didn't set errno, assume problem is no disk space */
! if (returnCode != amount && errno == 0)
! errno = ENOSPC;
! if (returnCode > 0)
! VfdCache[file].seekPos += returnCode;
! else
! {
! #ifdef WIN32
! DWORD error = GetLastError();
!
! switch (error)
! {
! /* see comments in FileRead() */
! case ERROR_NO_SYSTEM_RESOURCES:
! pg_usleep(1000);
! errno = EINTR;
! break;
! default:
! _dosmaperr(error);
! Assert(errno != EINTR);
! }
! #endif
! /* Ok if interrupted and retry */
! if (errno == EINTR)
! continue;
!
! VfdCache[file].seekPos = FileUnknownPos;
! }
!
! break;
! }
return returnCode; }