The attached patch improves pg_ctl's win32 service code to eliminate
authorBruce Momjian <bruce@momjian.us>
Sat, 28 Aug 2004 23:26:37 +0000 (23:26 +0000)
committerBruce Momjian <bruce@momjian.us>
Sat, 28 Aug 2004 23:26:37 +0000 (23:26 +0000)
some possible causes of the stale postmaster.pid problem that some users
have reported.

- The service did not properly report that it accepts
SERVICE_CONTROL_SHUTDOWN events, thus it's possible the SCM simply
killed the postmaster on shutdown.

- 'WaitHints' are now given to the SCM to prevent it timing out if
pg_ctl doesn't respond to a control event quickly enough.

- During shutdown, the service checkpoint counter is incremented every
five seconds for up to a minute to prevent the SCM timing out and
assuming the service is not responding.

Dave Page

src/bin/pg_ctl/pg_ctl.c

index 40de6ae97e829f0ea68df3228ccc93d18ea295b3..569b49759d6a94c9a1ab3f5ea41c0e712082bfa2 100644 (file)
@@ -4,7 +4,7 @@
  *
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.27 2004/08/28 22:04:01 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.28 2004/08/28 23:26:37 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -938,12 +938,18 @@ static void WINAPI pgwin32_ServiceHandler(DWORD request)
    {
        case SERVICE_CONTROL_STOP:
        case SERVICE_CONTROL_SHUTDOWN:
+           /* 
+            * We only need a short wait hint here as it just needs to wait for
+            * the next checkpoint. They occur every 5 seconds during shutdown
+            */
+           status.dwWaitHint = 10000; 
            pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
            SetEvent(shutdownEvent);
            return;
 
        case SERVICE_CONTROL_PAUSE:
            /* Win32 config reloading */
+           status.dwWaitHint = 5000;
            kill(postmasterPID,SIGHUP);
            return;
 
@@ -964,9 +970,9 @@ static void WINAPI pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
    /* Initialize variables */
    status.dwWin32ExitCode  = S_OK;
    status.dwCheckPoint     = 0;
-   status.dwWaitHint       = 0;
+   status.dwWaitHint       = 60000;
    status.dwServiceType    = SERVICE_WIN32_OWN_PROCESS;
-   status.dwControlsAccepted           = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_PAUSE_CONTINUE;
+   status.dwControlsAccepted           = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN|SERVICE_ACCEPT_PAUSE_CONTINUE;
    status.dwServiceSpecificExitCode    = 0;
    status.dwCurrentState = SERVICE_START_PENDING;
 
@@ -1000,7 +1006,15 @@ static void WINAPI pgwin32_ServiceMain(DWORD argc, LPTSTR *argv)
    {
        case WAIT_OBJECT_0: /* shutdown event */
            kill(postmasterPID,SIGINT);
-           WaitForSingleObject(postmasterProcess,INFINITE);
+       
+           /* 
+            * Increment the checkpoint and try again
+            * Abort after 12 checkpoints as the postmaster has probably hung 
+            */
+           while (WaitForSingleObject(postmasterProcess,5000) == WAIT_TIMEOUT && status.dwCheckPoint < 12)
+           {
+               status.dwCheckPoint++;
+           }
            break;
 
        case (WAIT_OBJECT_0+1): /* postmaster went down */