Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a1587e4

Browse files
committed
- Fix the -w (wait) option to work in Windows service mode, per bug #3382.
- Prevent the -w option being passed to the postmaster. - Read the postmaster options file when starting as a Windows service. Dave Page
1 parent 1c7fe33 commit a1587e4

File tree

1 file changed

+87
-35
lines changed

1 file changed

+87
-35
lines changed

src/bin/pg_ctl/pg_ctl.c

+87-35
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
66
*
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 $
88
*
99
*-------------------------------------------------------------------------
1010
*/
@@ -126,11 +126,22 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
126126
static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
127127
static void pgwin32_doRunAsService(void);
128128
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]
129137
#endif
138+
130139
static pgpid_t get_pgpid(void);
131140
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);
134145
static bool postmaster_is_alive(pid_t pid);
135146

136147
static char def_postopts_file[MAXPGPATH];
@@ -391,15 +402,20 @@ start_postmaster(void)
391402

392403

393404

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+
*/
395410
static bool
396-
test_postmaster_connection(void)
411+
test_postmaster_connection(bool do_checkpoint)
397412
{
398413
PGconn *conn;
399414
bool success = false;
400415
int i;
401416
char portstr[32];
402417
char *p;
418+
char connstr[128]; /* Should be way more than enough! */
403419

404420
*portstr = '\0';
405421

@@ -464,10 +480,12 @@ test_postmaster_connection(void)
464480
if (!*portstr)
465481
snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);
466482

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+
467486
for (i = 0; i < wait_seconds; i++)
468487
{
469-
if ((conn = PQsetdbLogin(NULL, portstr, NULL, NULL,
470-
"postgres", NULL, NULL)) != NULL &&
488+
if ((conn = PQconnectdb(connstr)) != NULL &&
471489
(PQstatus(conn) == CONNECTION_OK ||
472490
(strcmp(PQerrorMessage(conn),
473491
PQnoPasswordSupplied) == 0)))
@@ -479,7 +497,25 @@ test_postmaster_connection(void)
479497
else
480498
{
481499
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+
483519
pg_usleep(1000000); /* 1 sec */
484520
}
485521
}
@@ -508,24 +544,10 @@ unlimit_core_size(void)
508544
}
509545
#endif
510546

511-
512-
513547
static void
514-
do_start(void)
548+
read_post_opts(void)
515549
{
516-
pgpid_t pid;
517-
pgpid_t old_pid = 0;
518550
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-
}
529551

530552
if (post_opts == NULL)
531553
{
@@ -536,7 +558,7 @@ do_start(void)
536558
postopts_file : def_postopts_file);
537559
if (optlines == NULL)
538560
{
539-
if (ctl_command == START_COMMAND)
561+
if (ctl_command == START_COMMAND || ctl_command == RUN_AS_SERVICE_COMMAND)
540562
post_opts = "";
541563
else
542564
{
@@ -576,6 +598,25 @@ do_start(void)
576598
post_opts = optline;
577599
}
578600
}
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();
579620

580621
/* No -D or -D already added during server start */
581622
if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
@@ -642,7 +683,7 @@ do_start(void)
642683
{
643684
print_msg(_("waiting for server to start..."));
644685

645-
if (test_postmaster_connection() == false)
686+
if (test_postmaster_connection(false) == false)
646687
{
647688
printf(_("could not start server\n"));
648689
exit(1);
@@ -982,7 +1023,7 @@ pgwin32_CommandLine(bool registration)
9821023
strcat(cmdLine, "\"");
9831024
}
9841025

985-
if (do_wait)
1026+
if (registration && do_wait)
9861027
strcat(cmdLine, " -w");
9871028

9881029
if (post_opts)
@@ -1065,15 +1106,6 @@ pgwin32_doUnregister(void)
10651106
CloseServiceHandle(hSCM);
10661107
}
10671108

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-
10771109
static void
10781110
pgwin32_SetServiceStatus(DWORD currentState)
10791111
{
@@ -1118,6 +1150,7 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
11181150
{
11191151
PROCESS_INFORMATION pi;
11201152
DWORD ret;
1153+
DWORD check_point_start;
11211154

11221155
/* Initialize variables */
11231156
status.dwWin32ExitCode = S_OK;
@@ -1130,6 +1163,8 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
11301163

11311164
memset(&pi, 0, sizeof(pi));
11321165

1166+
read_post_opts();
1167+
11331168
/* Register the control request handler */
11341169
if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
11351170
return;
@@ -1147,10 +1182,27 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
11471182
postmasterPID = pi.dwProcessId;
11481183
postmasterProcess = pi.hProcess;
11491184
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+
11501201
pgwin32_SetServiceStatus(SERVICE_RUNNING);
11511202

11521203
/* Wait for quit... */
11531204
ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
1205+
11541206
pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
11551207
switch (ret)
11561208
{

0 commit comments

Comments
 (0)