mirror of
https://github.com/postgres/postgres.git
synced 2025-04-25 21:42:33 +03:00
- 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
This commit is contained in:
parent
1c7fe33fdb
commit
a1587e41ae
@ -4,7 +4,7 @@
|
|||||||
*
|
*
|
||||||
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.80 2007/05/31 15:13:04 petere Exp $
|
* $PostgreSQL: pgsql/src/bin/pg_ctl/pg_ctl.c,v 1.81 2007/07/02 21:58:31 mha Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -126,11 +126,22 @@ static void WINAPI pgwin32_ServiceHandler(DWORD);
|
|||||||
static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
|
static void WINAPI pgwin32_ServiceMain(DWORD, LPTSTR *);
|
||||||
static void pgwin32_doRunAsService(void);
|
static void pgwin32_doRunAsService(void);
|
||||||
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION * processInfo);
|
static int CreateRestrictedProcess(char *cmd, PROCESS_INFORMATION * processInfo);
|
||||||
|
|
||||||
|
static SERVICE_STATUS status;
|
||||||
|
static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
|
||||||
|
static HANDLE shutdownHandles[2];
|
||||||
|
static pid_t postmasterPID = -1;
|
||||||
|
|
||||||
|
#define shutdownEvent shutdownHandles[0]
|
||||||
|
#define postmasterProcess shutdownHandles[1]
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static pgpid_t get_pgpid(void);
|
static pgpid_t get_pgpid(void);
|
||||||
static char **readfile(const char *path);
|
static char **readfile(const char *path);
|
||||||
static int start_postmaster(void);
|
static int start_postmaster(void);
|
||||||
static bool test_postmaster_connection(void);
|
static void read_post_opts(void);
|
||||||
|
|
||||||
|
static bool test_postmaster_connection(bool);
|
||||||
static bool postmaster_is_alive(pid_t pid);
|
static bool postmaster_is_alive(pid_t pid);
|
||||||
|
|
||||||
static char def_postopts_file[MAXPGPATH];
|
static char def_postopts_file[MAXPGPATH];
|
||||||
@ -391,15 +402,20 @@ start_postmaster(void)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Find the pgport and try a connection */
|
/*
|
||||||
|
* Find the pgport and try a connection
|
||||||
|
* Note that the checkpoint parameter enables a Windows service control
|
||||||
|
* manager checkpoint, it's got nothing to do with database checkpoints!!
|
||||||
|
*/
|
||||||
static bool
|
static bool
|
||||||
test_postmaster_connection(void)
|
test_postmaster_connection(bool do_checkpoint)
|
||||||
{
|
{
|
||||||
PGconn *conn;
|
PGconn *conn;
|
||||||
bool success = false;
|
bool success = false;
|
||||||
int i;
|
int i;
|
||||||
char portstr[32];
|
char portstr[32];
|
||||||
char *p;
|
char *p;
|
||||||
|
char connstr[128]; /* Should be way more than enough! */
|
||||||
|
|
||||||
*portstr = '\0';
|
*portstr = '\0';
|
||||||
|
|
||||||
@ -464,10 +480,12 @@ test_postmaster_connection(void)
|
|||||||
if (!*portstr)
|
if (!*portstr)
|
||||||
snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);
|
snprintf(portstr, sizeof(portstr), "%d", DEF_PGPORT);
|
||||||
|
|
||||||
|
/* We need to set a connect timeout otherwise on Windows the SCM will probably timeout first */
|
||||||
|
snprintf(connstr, sizeof(connstr), "dbname=postgres port=%s connect_timeout=5", portstr);
|
||||||
|
|
||||||
for (i = 0; i < wait_seconds; i++)
|
for (i = 0; i < wait_seconds; i++)
|
||||||
{
|
{
|
||||||
if ((conn = PQsetdbLogin(NULL, portstr, NULL, NULL,
|
if ((conn = PQconnectdb(connstr)) != NULL &&
|
||||||
"postgres", NULL, NULL)) != NULL &&
|
|
||||||
(PQstatus(conn) == CONNECTION_OK ||
|
(PQstatus(conn) == CONNECTION_OK ||
|
||||||
(strcmp(PQerrorMessage(conn),
|
(strcmp(PQerrorMessage(conn),
|
||||||
PQnoPasswordSupplied) == 0)))
|
PQnoPasswordSupplied) == 0)))
|
||||||
@ -479,7 +497,25 @@ test_postmaster_connection(void)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
PQfinish(conn);
|
PQfinish(conn);
|
||||||
print_msg(".");
|
|
||||||
|
#if defined(WIN32)
|
||||||
|
if (do_checkpoint)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Increment the wait hint by 6 secs (connection timeout + sleep)
|
||||||
|
* We must do this to indicate to the SCM that our startup time is
|
||||||
|
* changing, otherwise it'll usually send a stop signal after 20
|
||||||
|
* seconds, despite incrementing the checkpoint counter.
|
||||||
|
*/
|
||||||
|
status.dwWaitHint += 6000;
|
||||||
|
status.dwCheckPoint++;
|
||||||
|
SetServiceStatus(hStatus, (LPSERVICE_STATUS) &status);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
print_msg(".");
|
||||||
|
|
||||||
pg_usleep(1000000); /* 1 sec */
|
pg_usleep(1000000); /* 1 sec */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -508,24 +544,10 @@ unlimit_core_size(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
do_start(void)
|
read_post_opts(void)
|
||||||
{
|
{
|
||||||
pgpid_t pid;
|
|
||||||
pgpid_t old_pid = 0;
|
|
||||||
char *optline = NULL;
|
char *optline = NULL;
|
||||||
int exitcode;
|
|
||||||
|
|
||||||
if (ctl_command != RESTART_COMMAND)
|
|
||||||
{
|
|
||||||
old_pid = get_pgpid();
|
|
||||||
if (old_pid != 0)
|
|
||||||
write_stderr(_("%s: another server might be running; "
|
|
||||||
"trying to start server anyway\n"),
|
|
||||||
progname);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (post_opts == NULL)
|
if (post_opts == NULL)
|
||||||
{
|
{
|
||||||
@ -536,7 +558,7 @@ do_start(void)
|
|||||||
postopts_file : def_postopts_file);
|
postopts_file : def_postopts_file);
|
||||||
if (optlines == NULL)
|
if (optlines == NULL)
|
||||||
{
|
{
|
||||||
if (ctl_command == START_COMMAND)
|
if (ctl_command == START_COMMAND || ctl_command == RUN_AS_SERVICE_COMMAND)
|
||||||
post_opts = "";
|
post_opts = "";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -576,6 +598,25 @@ do_start(void)
|
|||||||
post_opts = optline;
|
post_opts = optline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_start(void)
|
||||||
|
{
|
||||||
|
pgpid_t pid;
|
||||||
|
pgpid_t old_pid = 0;
|
||||||
|
int exitcode;
|
||||||
|
|
||||||
|
if (ctl_command != RESTART_COMMAND)
|
||||||
|
{
|
||||||
|
old_pid = get_pgpid();
|
||||||
|
if (old_pid != 0)
|
||||||
|
write_stderr(_("%s: another server might be running; "
|
||||||
|
"trying to start server anyway\n"),
|
||||||
|
progname);
|
||||||
|
}
|
||||||
|
|
||||||
|
read_post_opts();
|
||||||
|
|
||||||
/* No -D or -D already added during server start */
|
/* No -D or -D already added during server start */
|
||||||
if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
|
if (ctl_command == RESTART_COMMAND || pgdata_opt == NULL)
|
||||||
@ -642,7 +683,7 @@ do_start(void)
|
|||||||
{
|
{
|
||||||
print_msg(_("waiting for server to start..."));
|
print_msg(_("waiting for server to start..."));
|
||||||
|
|
||||||
if (test_postmaster_connection() == false)
|
if (test_postmaster_connection(false) == false)
|
||||||
{
|
{
|
||||||
printf(_("could not start server\n"));
|
printf(_("could not start server\n"));
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -982,7 +1023,7 @@ pgwin32_CommandLine(bool registration)
|
|||||||
strcat(cmdLine, "\"");
|
strcat(cmdLine, "\"");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (do_wait)
|
if (registration && do_wait)
|
||||||
strcat(cmdLine, " -w");
|
strcat(cmdLine, " -w");
|
||||||
|
|
||||||
if (post_opts)
|
if (post_opts)
|
||||||
@ -1065,15 +1106,6 @@ pgwin32_doUnregister(void)
|
|||||||
CloseServiceHandle(hSCM);
|
CloseServiceHandle(hSCM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static SERVICE_STATUS status;
|
|
||||||
static SERVICE_STATUS_HANDLE hStatus = (SERVICE_STATUS_HANDLE) 0;
|
|
||||||
static HANDLE shutdownHandles[2];
|
|
||||||
static pid_t postmasterPID = -1;
|
|
||||||
|
|
||||||
#define shutdownEvent shutdownHandles[0]
|
|
||||||
#define postmasterProcess shutdownHandles[1]
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pgwin32_SetServiceStatus(DWORD currentState)
|
pgwin32_SetServiceStatus(DWORD currentState)
|
||||||
{
|
{
|
||||||
@ -1118,6 +1150,7 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
|
|||||||
{
|
{
|
||||||
PROCESS_INFORMATION pi;
|
PROCESS_INFORMATION pi;
|
||||||
DWORD ret;
|
DWORD ret;
|
||||||
|
DWORD check_point_start;
|
||||||
|
|
||||||
/* Initialize variables */
|
/* Initialize variables */
|
||||||
status.dwWin32ExitCode = S_OK;
|
status.dwWin32ExitCode = S_OK;
|
||||||
@ -1130,6 +1163,8 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
|
|||||||
|
|
||||||
memset(&pi, 0, sizeof(pi));
|
memset(&pi, 0, sizeof(pi));
|
||||||
|
|
||||||
|
read_post_opts();
|
||||||
|
|
||||||
/* Register the control request handler */
|
/* Register the control request handler */
|
||||||
if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
|
if ((hStatus = RegisterServiceCtrlHandler(register_servicename, pgwin32_ServiceHandler)) == (SERVICE_STATUS_HANDLE) 0)
|
||||||
return;
|
return;
|
||||||
@ -1147,10 +1182,27 @@ pgwin32_ServiceMain(DWORD argc, LPTSTR * argv)
|
|||||||
postmasterPID = pi.dwProcessId;
|
postmasterPID = pi.dwProcessId;
|
||||||
postmasterProcess = pi.hProcess;
|
postmasterProcess = pi.hProcess;
|
||||||
CloseHandle(pi.hThread);
|
CloseHandle(pi.hThread);
|
||||||
|
|
||||||
|
if (do_wait)
|
||||||
|
{
|
||||||
|
write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Waiting for server startup...\n"));
|
||||||
|
if (test_postmaster_connection(true) == false)
|
||||||
|
{
|
||||||
|
write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Timed out waiting for server startup\n"));
|
||||||
|
pgwin32_SetServiceStatus(SERVICE_STOPPED);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
write_eventlog(EVENTLOG_INFORMATION_TYPE, _("Server started and accepting connections\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save the checkpoint value as it might have been incremented in test_postmaster_connection */
|
||||||
|
check_point_start = status.dwCheckPoint;
|
||||||
|
|
||||||
pgwin32_SetServiceStatus(SERVICE_RUNNING);
|
pgwin32_SetServiceStatus(SERVICE_RUNNING);
|
||||||
|
|
||||||
/* Wait for quit... */
|
/* Wait for quit... */
|
||||||
ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
|
ret = WaitForMultipleObjects(2, shutdownHandles, FALSE, INFINITE);
|
||||||
|
|
||||||
pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
|
pgwin32_SetServiceStatus(SERVICE_STOP_PENDING);
|
||||||
switch (ret)
|
switch (ret)
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user