4
4
*
5
5
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
6
6
*
7
- * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.80 2007/05/31 15:13:04 petere Exp $
7
+ * $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.81 2007/07/02 21:58:31 mha Exp $
8
8
*
9
9
*-------------------------------------------------------------------------
10
10
*/
@@ -126,11 +126,22 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
126
126
static void WINAPI pgwin32_ServiceMain (DWORD , LPTSTR * );
127
127
static void pgwin32_doRunAsService (void );
128
128
static int CreateRestrictedProcess (char * cmd , PROCESS_INFORMATION * processInfo );
129
+
130
+ static SERVICE_STATUS status ;
131
+ static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE ) 0 ;
132
+ static HANDLE shutdownHandles [2 ];
133
+ static pid_t postmasterPID = -1 ;
134
+
135
+ #define shutdownEvent shutdownHandles[0]
136
+ #define postmasterProcess shutdownHandles[1]
129
137
#endif
138
+
130
139
static pgpid_t get_pgpid (void );
131
140
static char * * readfile (const char * path );
132
- static int start_postmaster (void );
133
- static bool test_postmaster_connection (void );
141
+ static int start_postmaster (void );
142
+ static void read_post_opts (void );
143
+
144
+ static bool test_postmaster_connection (bool );
134
145
static bool postmaster_is_alive (pid_t pid );
135
146
136
147
static char def_postopts_file [MAXPGPATH ];
@@ -391,15 +402,20 @@ start_postmaster(void)
391
402
392
403
393
404
394
- /* Find the pgport and try a connection */
405
+ /*
406
+ * Find the pgport and try a connection
407
+ * Note that the checkpoint parameter enables a Windows service control
408
+ * manager checkpoint, it's got nothing to do with database checkpoints!!
409
+ */
395
410
static bool
396
- test_postmaster_connection (void )
411
+ test_postmaster_connection (bool do_checkpoint )
397
412
{
398
413
PGconn * conn ;
399
414
bool success = false;
400
415
int i ;
401
416
char portstr [32 ];
402
417
char * p ;
418
+ char connstr [128 ]; /* Should be way more than enough! */
403
419
404
420
* portstr = '\0' ;
405
421
@@ -464,10 +480,12 @@ test_postmaster_connection(void)
464
480
if (!* portstr )
465
481
snprintf (portstr , sizeof (portstr ), "%d" , DEF_PGPORT );
466
482
483
+ /* We need to set a connect timeout otherwise on Windows the SCM will probably timeout first */
484
+ snprintf (connstr , sizeof (connstr ), "dbname=postgres port=%s connect_timeout=5" , portstr );
485
+
467
486
for (i = 0 ; i < wait_seconds ; i ++ )
468
487
{
469
- if ((conn = PQsetdbLogin (NULL , portstr , NULL , NULL ,
470
- "postgres" , NULL , NULL )) != NULL &&
488
+ if ((conn = PQconnectdb (connstr )) != NULL &&
471
489
(PQstatus (conn ) == CONNECTION_OK ||
472
490
(strcmp (PQerrorMessage (conn ),
473
491
PQnoPasswordSupplied ) == 0 )))
@@ -479,7 +497,25 @@ test_postmaster_connection(void)
479
497
else
480
498
{
481
499
PQfinish (conn );
482
- print_msg ("." );
500
+
501
+ #if defined(WIN32 )
502
+ if (do_checkpoint )
503
+ {
504
+ /*
505
+ * Increment the wait hint by 6 secs (connection timeout + sleep)
506
+ * We must do this to indicate to the SCM that our startup time is
507
+ * changing, otherwise it'll usually send a stop signal after 20
508
+ * seconds, despite incrementing the checkpoint counter.
509
+ */
510
+ status .dwWaitHint += 6000 ;
511
+ status .dwCheckPoint ++ ;
512
+ SetServiceStatus (hStatus , (LPSERVICE_STATUS ) & status );
513
+ }
514
+
515
+ else
516
+ #endif
517
+ print_msg ("." );
518
+
483
519
pg_usleep (1000000 ); /* 1 sec */
484
520
}
485
521
}
@@ -508,24 +544,10 @@ unlimit_core_size(void)
508
544
}
509
545
#endif
510
546
511
-
512
-
513
547
static void
514
- do_start (void )
548
+ read_post_opts (void )
515
549
{
516
- pgpid_t pid ;
517
- pgpid_t old_pid = 0 ;
518
550
char * optline = NULL ;
519
- int exitcode ;
520
-
521
- if (ctl_command != RESTART_COMMAND )
522
- {
523
- old_pid = get_pgpid ();
524
- if (old_pid != 0 )
525
- write_stderr (_ ("%s: another server might be running; "
526
- "trying to start server anyway\n" ),
527
- progname );
528
- }
529
551
530
552
if (post_opts == NULL )
531
553
{
@@ -536,7 +558,7 @@ do_start(void)
536
558
postopts_file : def_postopts_file );
537
559
if (optlines == NULL )
538
560
{
539
- if (ctl_command == START_COMMAND )
561
+ if (ctl_command == START_COMMAND || ctl_command == RUN_AS_SERVICE_COMMAND )
540
562
post_opts = "" ;
541
563
else
542
564
{
@@ -576,6 +598,25 @@ do_start(void)
576
598
post_opts = optline ;
577
599
}
578
600
}
601
+ }
602
+
603
+ static void
604
+ do_start (void )
605
+ {
606
+ pgpid_t pid ;
607
+ pgpid_t old_pid = 0 ;
608
+ int exitcode ;
609
+
610
+ if (ctl_command != RESTART_COMMAND )
611
+ {
612
+ old_pid = get_pgpid ();
613
+ if (old_pid != 0 )
614
+ write_stderr (_ ("%s: another server might be running; "
615
+ "trying to start server anyway\n" ),
616
+ progname );
617
+ }
618
+
619
+ read_post_opts ();
579
620
580
621
/* No -D or -D already added during server start */
581
622
if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL )
@@ -642,7 +683,7 @@ do_start(void)
642
683
{
643
684
print_msg (_ ("waiting for server to start..." ));
644
685
645
- if (test_postmaster_connection () == false)
686
+ if (test_postmaster_connection (false ) == false)
646
687
{
647
688
printf (_ ("could not start server\n" ));
648
689
exit (1 );
@@ -982,7 +1023,7 @@ pgwin32_CommandLine(bool registration)
982
1023
strcat (cmdLine , "\"" );
983
1024
}
984
1025
985
- if (do_wait )
1026
+ if (registration && do_wait )
986
1027
strcat (cmdLine , " -w" );
987
1028
988
1029
if (post_opts )
@@ -1065,15 +1106,6 @@ pgwin32_doUnregister(void)
1065
1106
CloseServiceHandle (hSCM );
1066
1107
}
1067
1108
1068
-
1069
- static SERVICE_STATUS status ;
1070
- static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE ) 0 ;
1071
- static HANDLE shutdownHandles [2 ];
1072
- static pid_t postmasterPID = -1 ;
1073
-
1074
- #define shutdownEvent shutdownHandles[0]
1075
- #define postmasterProcess shutdownHandles[1]
1076
-
1077
1109
static void
1078
1110
pgwin32_SetServiceStatus (DWORD currentState )
1079
1111
{
@@ -1118,6 +1150,7 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
1118
1150
{
1119
1151
PROCESS_INFORMATION pi ;
1120
1152
DWORD ret ;
1153
+ DWORD check_point_start ;
1121
1154
1122
1155
/* Initialize variables */
1123
1156
status .dwWin32ExitCode = S_OK ;
@@ -1130,6 +1163,8 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
1130
1163
1131
1164
memset (& pi , 0 , sizeof (pi ));
1132
1165
1166
+ read_post_opts ();
1167
+
1133
1168
/* Register the control request handler */
1134
1169
if ((hStatus = RegisterServiceCtrlHandler (register_servicename , pgwin32_ServiceHandler )) == (SERVICE_STATUS_HANDLE ) 0 )
1135
1170
return ;
@@ -1147,10 +1182,27 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
1147
1182
postmasterPID = pi .dwProcessId ;
1148
1183
postmasterProcess = pi .hProcess ;
1149
1184
CloseHandle (pi .hThread );
1185
+
1186
+ if (do_wait )
1187
+ {
1188
+ write_eventlog (EVENTLOG_INFORMATION_TYPE , _ ("Waiting for server startup...\n" ));
1189
+ if (test_postmaster_connection (true) == false)
1190
+ {
1191
+ write_eventlog (EVENTLOG_INFORMATION_TYPE , _ ("Timed out waiting for server startup\n" ));
1192
+ pgwin32_SetServiceStatus (SERVICE_STOPPED );
1193
+ return ;
1194
+ }
1195
+ write_eventlog (EVENTLOG_INFORMATION_TYPE , _ ("Server started and accepting connections\n" ));
1196
+ }
1197
+
1198
+ /* Save the checkpoint value as it might have been incremented in test_postmaster_connection */
1199
+ check_point_start = status .dwCheckPoint ;
1200
+
1150
1201
pgwin32_SetServiceStatus (SERVICE_RUNNING );
1151
1202
1152
1203
/* Wait for quit... */
1153
1204
ret = WaitForMultipleObjects (2 , shutdownHandles , FALSE, INFINITE );
1205
+
1154
1206
pgwin32_SetServiceStatus (SERVICE_STOP_PENDING );
1155
1207
switch (ret )
1156
1208
{
0 commit comments