Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitbb24439

Browse files
committed
Detach postmaster process from pg_ctl's session at server startup.
pg_ctl is supposed to daemonize the postmaster process, so that it's notaffected by signals to the launching process group. Before this patch, ifyou had a shell script that used "pg_ctl start", and you interrupted theshell script after postmaster had been launched, postmaster was alsokilled. To fix, call setsid() after forking the postmaster process.Long time ago, we had a 'silent_mode' option, which daemonized thepostmaster process by calling setsid(), but that was removed back in 2011(commitf7ea6be). We discussed bringing that back in some form, butpg_ctl is the documented way of launching postmaster to the background, soputting the setsid() call in pg_ctl itself seems appropriate.Just putting postmaster in a separate session would change the behaviorwhen you interrupt "pg_ctl -w start", e.g. with CTRL-C, while it's waitingfor postmaster to start. The historical behavior has been thatinterrupting pg_ctl aborts the server launch, which is handy if the serveris stuck in recovery, for example, and won't fully start up. To keep thatbehavior, install a signal handler in pg_ctl, to explicitly killpostmaster, if pg_ctl is interrupted while it's waiting for the server tostart up. This isn't 100% watertight, there is a small window afterforking the postmaster process, where the signal handler doesn't know thepostmaster's PID yet, but seems good enough.Arguably this is a long-standing bug, but I refrained from back-batching,out of fear of breaking someone's scripts that depended on the oldbehavior.Reviewed by Tom Lane. Report and original patch by Paul Guo, withfeedback from Michael Paquier.Discussion:https://www.postgresql.org/message-id/CAEET0ZH5Bf7dhZB3mYy8zZQttJrdZg_0Wwaj0o1PuuBny1JkEw%40mail.gmail.com
1 parentd9cdb1b commitbb24439

File tree

1 file changed

+51
-1
lines changed

1 file changed

+51
-1
lines changed

‎src/bin/pg_ctl/pg_ctl.c

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,12 +103,13 @@ static char backup_file[MAXPGPATH];
103103
staticcharpromote_file[MAXPGPATH];
104104
staticcharlogrotate_file[MAXPGPATH];
105105

106+
staticvolatilepgpid_tpostmasterPID=-1;
107+
106108
#ifdefWIN32
107109
staticDWORDpgctl_start_type=SERVICE_AUTO_START;
108110
staticSERVICE_STATUSstatus;
109111
staticSERVICE_STATUS_HANDLEhStatus= (SERVICE_STATUS_HANDLE)0;
110112
staticHANDLEshutdownHandles[2];
111-
staticpid_tpostmasterPID=-1;
112113

113114
#defineshutdownEvent shutdownHandles[0]
114115
#definepostmasterProcess shutdownHandles[1]
@@ -471,6 +472,20 @@ start_postmaster(void)
471472

472473
/* fork succeeded, in child */
473474

475+
/*
476+
* If possible, detach the postmaster process from the launching process
477+
* group and make it a group leader, so that it doesn't get signaled along
478+
* with the current group that launched it.
479+
*/
480+
#ifdefHAVE_SETSID
481+
if (setsid()<0)
482+
{
483+
write_stderr(_("%s: could not start server due to setsid() failure: %s\n"),
484+
progname,strerror(errno));
485+
exit(1);
486+
}
487+
#endif
488+
474489
/*
475490
* Since there might be quotes to handle here, it is easier simply to pass
476491
* everything to a shell to process them. Use exec so that the postmaster
@@ -719,6 +734,30 @@ read_post_opts(void)
719734
}
720735
}
721736

737+
/*
738+
* SIGINT signal handler used while waiting for postmaster to start up.
739+
* Forwards the SIGINT to the postmaster process, asking it to shut down,
740+
* before terminating pg_ctl itself. This way, if the user hits CTRL-C while
741+
* waiting for the server to start up, the server launch is aborted.
742+
*/
743+
staticvoid
744+
trap_sigint_during_startup(intsig)
745+
{
746+
if (postmasterPID!=-1)
747+
{
748+
if (kill(postmasterPID,SIGINT)!=0)
749+
write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"),
750+
progname, (pgpid_t)postmasterPID,strerror(errno));
751+
}
752+
753+
/*
754+
* Clear the signal handler, and send the signal again, to terminate the
755+
* process as normal.
756+
*/
757+
pqsignal(SIGINT,SIG_DFL);
758+
raise(SIGINT);
759+
}
760+
722761
staticchar*
723762
find_other_exec_or_die(constchar*argv0,constchar*target,constchar*versionstr)
724763
{
@@ -827,6 +866,17 @@ do_start(void)
827866

828867
if (do_wait)
829868
{
869+
/*
870+
* If the user interrupts the startup (e.g. with CTRL-C), we'd like to
871+
* abort the server launch. Install a signal handler that will
872+
* forward SIGINT to the postmaster process, while we wait.
873+
*
874+
* (We don't bother to reset the signal handler after the launch, as
875+
* we're about to exit, anyway.)
876+
*/
877+
postmasterPID=pm_pid;
878+
pqsignal(SIGINT,trap_sigint_during_startup);
879+
830880
print_msg(_("waiting for server to start..."));
831881

832882
switch (wait_for_postmaster(pm_pid, false))

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp