Andrew Dunstan wrote:
> 
> 
> Magnus Hagander wrote:
>>
>> Andrew, you want to write up a patch or do you want me to do it?
>>
>>
>>   
> 
> Go for it.

How does this look?

Passes my tests, but I can't really reproduce the requirement to retry,
so I haven't been able to test that part :(

//Magnus

*** a/src/backend/port/win32_shmem.c
--- b/src/backend/port/win32_shmem.c
***************
*** 123,128 **** PGSharedMemoryCreate(Size size, bool makePrivate, int port)
--- 123,129 ----
  	HANDLE		hmap,
  				hmap2;
  	char	   *szShareMem;
+ 	int			i;
  
  	/* Room for a header? */
  	Assert(size > MAXALIGN(sizeof(PGShmemHeader)));
***************
*** 131,184 **** PGSharedMemoryCreate(Size size, bool makePrivate, int port)
  
  	UsedShmemSegAddr = NULL;
  
- 	/* In case CreateFileMapping() doesn't set the error code to 0 on success */
- 	SetLastError(0);
- 
- 	hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF,		/* Use the pagefile */
- 							 NULL,		/* Default security attrs */
- 							 PAGE_READWRITE,	/* Memory is Read/Write */
- 							 0L,	/* Size Upper 32 Bits	*/
- 							 (DWORD) size,		/* Size Lower 32 bits */
- 							 szShareMem);
- 
- 	if (!hmap)
- 		ereport(FATAL,
- 				(errmsg("could not create shared memory segment: %lu", GetLastError()),
- 				 errdetail("Failed system call was CreateFileMapping(size=%lu, name=%s).",
- 						   (unsigned long) size, szShareMem)));
- 
  	/*
! 	 * If the segment already existed, CreateFileMapping() will return a
! 	 * handle to the existing one.
  	 */
! 	if (GetLastError() == ERROR_ALREADY_EXISTS)
  	{
- 		/*
- 		 * When recycling a shared memory segment, it may take a short while
- 		 * before it gets dropped from the global namespace. So re-try after
- 		 * sleeping for a second.
- 		 */
- 		CloseHandle(hmap);		/* Close the old handle, since we got a valid
- 								 * one to the previous segment. */
- 
- 		Sleep(1000);
- 
  		/* In case CreateFileMapping() doesn't set the error code to 0 on success */
  		SetLastError(0);
  
! 		hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF, NULL, PAGE_READWRITE, 0L, (DWORD) size, szShareMem);
  		if (!hmap)
  			ereport(FATAL,
  					(errmsg("could not create shared memory segment: %lu", GetLastError()),
  					 errdetail("Failed system call was CreateFileMapping(size=%lu, name=%s).",
  							   (unsigned long) size, szShareMem)));
  
  		if (GetLastError() == ERROR_ALREADY_EXISTS)
! 			ereport(FATAL,
! 				 (errmsg("pre-existing shared memory block is still in use"),
! 				  errhint("Check if there are any old server processes still running, and terminate them.")));
  	}
  
  	free(szShareMem);
  
  	/*
--- 132,184 ----
  
  	UsedShmemSegAddr = NULL;
  
  	/*
! 	 * When recycling a shared memory segment, it may take a short while
! 	 * before it gets dropped from the global namespace. So re-try after
! 	 * sleeping for a second, and continue retrying 10 times.
! 	 * (both the 1 second time and the 10 retries are completely arbitrary)
  	 */
! 	for (i = 0; i < 10; i++)
  	{
  		/* In case CreateFileMapping() doesn't set the error code to 0 on success */
  		SetLastError(0);
  
! 		hmap = CreateFileMapping((HANDLE) 0xFFFFFFFF,		/* Use the pagefile */
! 								 NULL,		/* Default security attrs */
! 								 PAGE_READWRITE,	/* Memory is Read/Write */
! 								 0L,	/* Size Upper 32 Bits	*/
! 								 (DWORD) size,		/* Size Lower 32 bits */
! 								 szShareMem);
! 
  		if (!hmap)
  			ereport(FATAL,
  					(errmsg("could not create shared memory segment: %lu", GetLastError()),
  					 errdetail("Failed system call was CreateFileMapping(size=%lu, name=%s).",
  							   (unsigned long) size, szShareMem)));
  
+ 		/*
+ 		 * If the segment already existed, CreateFileMapping() will return a
+ 		 * handle to the existing one.
+ 		 */
  		if (GetLastError() == ERROR_ALREADY_EXISTS)
! 		{
! 			CloseHandle(hmap);		/* Close the old handle, since we got a valid
! 									 * one to the previous segment. */
! 			Sleep(1000);
! 			continue;
! 		}
! 		break;
  	}
  
+ 	/*
+ 	 * If the last call in the loop still returned ERROR_ALREADY_EXISTS, this shared memory
+ 	 * segment exists and we assume it belongs to somebody else.
+ 	 */
+ 	if (GetLastError() == ERROR_ALREADY_EXISTS)
+ 		ereport(FATAL,
+ 			 (errmsg("pre-existing shared memory block is still in use"),
+ 			  errhint("Check if there are any old server processes still running, and terminate them.")));
+ 
  	free(szShareMem);
  
  	/*
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to