Re: [Patch] Create a new session in postmaster by calling setsid()

2019-01-14 Thread Heikki Linnakangas

On 30/12/2018 22:56, Tom Lane wrote:

This comment needs copy-editing:

+ * If the user hits interrupts the startup (e.g. with CTRL-C), we'd

Looks good otherwise.


Thanks, fixed that, and pushed.

- Heikki




Re: [Patch] Create a new session in postmaster by calling setsid()

2018-12-30 Thread Tom Lane
Heikki Linnakangas  writes:
> Here's a patch to implement that. Seems to work. There is a small window 
> between launching postmaster and installing the signal handler, though, 
> where CTRL-C on pg_ctl will not abort the server launch. I think that's 
> acceptable.

Hm ... you could partially forestall that by installing the signal handler
first.  But then you have to assume that storing a pid_t variable is
atomic, which perhaps is bad?  Though it's hard to credit that any
platform would need multiple instructions to do that.  Also, I suppose
there's still a window, since the fork will necessarily occur some time
before you're able to store the child PID into the variable.

Another possible idea is to block SIGINT from before the fork till after
you've set the variable.  But that seems overly complicated, and perhaps
not without problems of its own.  So on the whole I concur with your
approach.

> Forgot attachment, here it is.

This comment needs copy-editing:

+ * If the user hits interrupts the startup (e.g. with CTRL-C), we'd

Looks good otherwise.

regards, tom lane



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-12-30 Thread Heikki Linnakangas

On 30/12/2018 21:59, Heikki Linnakangas wrote:

On 28/12/2018 22:13, Tom Lane wrote:

Heikki Linnakangas  writes:

Another idea would be to call setsid() in pg_ctl, after forking
postmaster, like in Paul's original patch. That solves 1. and 2. To
still do 3., add a signal handler for SIGINT in pg_ctl, which forwards
the SIGINT to the postmaster process. Thoughts on that?


That seems like a nice idea.


Here's a patch to implement that.


Forgot attachment, here it is.

- Heikki
diff --git a/src/bin/pg_ctl/pg_ctl.c b/src/bin/pg_ctl/pg_ctl.c
index 1d0b056dde0..cb7b88bc7df 100644
--- a/src/bin/pg_ctl/pg_ctl.c
+++ b/src/bin/pg_ctl/pg_ctl.c
@@ -103,12 +103,13 @@ static char backup_file[MAXPGPATH];
 static char promote_file[MAXPGPATH];
 static char logrotate_file[MAXPGPATH];
 
+static volatile pgpid_t postmasterPID = -1;
+
 #ifdef WIN32
 static DWORD pgctl_start_type = SERVICE_AUTO_START;
 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]
@@ -471,6 +472,20 @@ start_postmaster(void)
 
 	/* fork succeeded, in child */
 
+	/*
+	 * If possible, detach the postmaster process from the launching process group
+	 * and make it a group leader, so that it doesn't get signaled along with the
+	 * current group that launched it.
+	 */
+#ifdef HAVE_SETSID
+	if (setsid() < 0)
+	{
+		write_stderr(_("%s: could not start server due to setsid() failure: %s\n"),
+	 progname, strerror(errno));
+		exit(1);
+	}
+#endif
+
 	/*
 	 * Since there might be quotes to handle here, it is easier simply to pass
 	 * everything to a shell to process them.  Use exec so that the postmaster
@@ -719,6 +734,30 @@ read_post_opts(void)
 	}
 }
 
+/*
+ * SIGINT signal handler used while waiting for postmaster to start up.
+ * Forwards the SIGINT to the postmaster process, asking it to shut down,
+ * before terminating pg_ctl itself. This way, if the user hits CTRL-C while
+ * waiting for the server to start up, the server launch is aborted.
+ */
+static void
+trap_sigint_during_startup(int sig)
+{
+	if (postmasterPID != -1)
+	{
+		if (kill(postmasterPID, SIGINT) != 0)
+			write_stderr(_("%s: could not send stop signal (PID: %ld): %s\n"),
+		 progname, (pgpid_t) postmasterPID, strerror(errno));
+	}
+
+	/*
+	 * Clear the signal handler, and send the signal again, to terminate the
+	 * process as normal.
+	 */
+	pqsignal(SIGINT, SIG_DFL);
+	raise(SIGINT);
+}
+
 static char *
 find_other_exec_or_die(const char *argv0, const char *target, const char *versionstr)
 {
@@ -827,6 +866,17 @@ do_start(void)
 
 	if (do_wait)
 	{
+		/*
+		 * If the user hits interrupts the startup (e.g. with CTRL-C), we'd
+		 * like to abort the server launch.  Install a signal handler that
+		 * will forward SIGINT to the postmaster process, while we wait.
+		 *
+		 * (We don't bother to reset the signal handler after the launch,
+		 * as we're about to exit, anyway.)
+		 */
+		postmasterPID = pm_pid;
+		pqsignal(SIGINT, trap_sigint_during_startup);
+
 		print_msg(_("waiting for server to start..."));
 
 		switch (wait_for_postmaster(pm_pid, false))


Re: [Patch] Create a new session in postmaster by calling setsid()

2018-12-28 Thread Tom Lane
Heikki Linnakangas  writes:
> We talked about adding a flag to postmaster, to tell it to call 
> setsid(). But I'm not sure what would be the appropriate time to do it. 

Yeah, there's no ideal time in the postmaster.

> Another idea would be to call setsid() in pg_ctl, after forking 
> postmaster, like in Paul's original patch. That solves 1. and 2. To 
> still do 3., add a signal handler for SIGINT in pg_ctl, which forwards 
> the SIGINT to the postmaster process. Thoughts on that?

That seems like a nice idea.

regards, tom lane



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-12-28 Thread Heikki Linnakangas

On 30/09/2018 15:47, Michael Paquier wrote:

On Thu, Sep 13, 2018 at 12:24:38PM -0700, Andres Freund wrote:

On 2018-09-13 15:27:58 +0800, Paul Guo wrote:

 From the respective of users instead of developers, I think for such
important
service, tty should be dissociated, i.e. postmaster should be daemonized by
default (and even should have default log filename?) or be setsid()-ed at
least.


I don't think it'd be good to switch to postgres daemonizing itself.  If
we were starting fresh, maybe, but there's plenty people invoking
postgres from scripts etc.  And tools like systemd don't actually want
daemons to fork away, so there's no clear need from that side either.


It seems to me that the thread is pointing out that we would not want
the postmaster to daemonize itself, but that something in pg_ctl could
be introduced, potentially optional.  I am marking this patch as
returned with feedback.


Hmm. So, the requirements are:

1. When launched from pg_ctl, postmaster should become leader of a new 
session and process group. To address Paul's original scenario.


2. If "postmaster" is launched stand-alone from terminal or a script, it 
should stay in foreground, in the parent session, so that it can be 
killed with Ctrl-C.


3. Hitting Ctrl-C while "pg_ctl start -w" is waiting for postmaster to 
start up, should "abort" and kill postmaster.


We talked about adding a flag to postmaster, to tell it to call 
setsid(). But I'm not sure what would be the appropriate time to do it. 
If it's done early during postmaster startup, then we still wouldn't 
have solved 3. Hitting Ctrl-C on pg_ctl, while the server is still in 
recovery, would not kill the server. We could do it after recovery has 
finished, but if we have already launched auxiliar processes, I think 
they would stay in the old process group and session. So I don't think 
that works.


Another idea would be to call setsid() in pg_ctl, after forking 
postmaster, like in Paul's original patch. That solves 1. and 2. To 
still do 3., add a signal handler for SIGINT in pg_ctl, which forwards 
the SIGINT to the postmaster process. Thoughts on that?


- Heikki



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-30 Thread Michael Paquier
On Thu, Sep 13, 2018 at 12:24:38PM -0700, Andres Freund wrote:
> On 2018-09-13 15:27:58 +0800, Paul Guo wrote:
>> From the respective of users instead of developers, I think for such
>> important
>> service, tty should be dissociated, i.e. postmaster should be daemonized by
>> default (and even should have default log filename?) or be setsid()-ed at
>> least.
> 
> I don't think it'd be good to switch to postgres daemonizing itself.  If
> we were starting fresh, maybe, but there's plenty people invoking
> postgres from scripts etc.  And tools like systemd don't actually want
> daemons to fork away, so there's no clear need from that side either.

It seems to me that the thread is pointing out that we would not want
the postmaster to daemonize itself, but that something in pg_ctl could
be introduced, potentially optional.  I am marking this patch as
returned with feedback.
--
Michael


signature.asc
Description: PGP signature


Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-13 Thread Andres Freund
Hi,

On 2018-09-13 15:27:58 +0800, Paul Guo wrote:
> From the respective of users instead of developers, I think for such
> important
> service, tty should be dissociated, i.e. postmaster should be daemonized by
> default (and even should have default log filename?) or be setsid()-ed at
> least.

I don't think it'd be good to switch to postgres daemonizing itself.  If
we were starting fresh, maybe, but there's plenty people invoking
postgres from scripts etc.  And tools like systemd don't actually want
daemons to fork away, so there's no clear need from that side either.


> I'm not sure the several-years-ago LINUX_OOM_ADJ issue (to resolve that,
> silient_mode was removed) still exists or not. I don't have context  about
> that, so
> I conceded to use setsid() even I prefer the deleted silent_mode code.

Yes, the OOM issues are still relevant.

Greetings,

Andres Freund



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-13 Thread Paul Guo
On Thu, Sep 13, 2018 at 8:20 AM, Michael Paquier 
wrote:

> On Wed, Sep 12, 2018 at 03:55:00PM -0400, Tom Lane wrote:
> > Although pg_ctl could sneak it in between forking and execing, it seems
> > like it'd be cleaner to have the postmaster proper do it in response to
> > a switch that pg_ctl passes it.  That avoids depending on the fork/exec
> > separation, and makes the functionality available for other postmaster
> > startup mechanisms, and opens the possibility of delaying the detach
> > to the end of startup.
>
> I would be fine with something happening only once the postmaster thinks
> that consistency has been reached and is open for business, though I'd
> still think that this should be controlled by a switch, where the
> default does what we do now.  Feel free to ignore me if I am outvoted ;)
> --
> Michael
>

>From the respective of users instead of developers, I think for such
important
service, tty should be dissociated, i.e. postmaster should be daemonized by
default (and even should have default log filename?) or be setsid()-ed at
least.
For concerns from developers, maybe a shell alias, or an internal switch in
pg_ctl,
or env variable guard in postmaster code could address.

I'm not sure the several-years-ago LINUX_OOM_ADJ issue (to resolve that,
silient_mode was removed) still exists or not. I don't have context  about
that, so
I conceded to use setsid() even I prefer the deleted silent_mode code.


Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Michael Paquier
On Wed, Sep 12, 2018 at 03:55:00PM -0400, Tom Lane wrote:
> Although pg_ctl could sneak it in between forking and execing, it seems
> like it'd be cleaner to have the postmaster proper do it in response to
> a switch that pg_ctl passes it.  That avoids depending on the fork/exec
> separation, and makes the functionality available for other postmaster
> startup mechanisms, and opens the possibility of delaying the detach
> to the end of startup.

I would be fine with something happening only once the postmaster thinks
that consistency has been reached and is open for business, though I'd
still think that this should be controlled by a switch, where the
default does what we do now.  Feel free to ignore me if I am outvoted ;)
--
Michael


signature.asc
Description: PGP signature


Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Tom Lane
Andrew Gierth  writes:
> "Tom" == Tom Lane  writes:
>  Tom> Hmph.  Can't we just ignore that error?

> If you ignore the error from setsid(), then you're still a process group
> leader (as you would be after running setsid()), but you're still
> attached to whatever controlling terminal (if any) you were previously
> attached to.

Oh, got it.  So actually, the setsid has to be done by what is/will be
the postmaster process.

Although pg_ctl could sneak it in between forking and execing, it seems
like it'd be cleaner to have the postmaster proper do it in response to
a switch that pg_ctl passes it.  That avoids depending on the fork/exec
separation, and makes the functionality available for other postmaster
startup mechanisms, and opens the possibility of delaying the detach
to the end of startup.

regards, tom lane



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Andrew Gierth
> "Tom" == Tom Lane  writes:

 >> The tricky part about doing setsid() is this: you're not allowed to
 >> do it if you're already a process group leader. silent_mode worked
 >> by having postmaster do another fork, exit in the parent, and do
 >> setsid() in the child.

 Tom> Hmph.  Can't we just ignore that error?

If you ignore the error from setsid(), then you're still a process group
leader (as you would be after running setsid()), but you're still
attached to whatever controlling terminal (if any) you were previously
attached to.

-- 
Andrew (irc:RhodiumToad)



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Tom Lane
Andrew Gierth  writes:
> "Tom" == Tom Lane  writes:
>  Tom> We'd likely need a switch to control that. If memory serves, there
>  Tom> used to be such a switch, but we got rid of the postmaster's
>  Tom> setsid call and the switch too. We probably should dig in the
>  Tom> archives and review the reasoning about that.

> The tricky part about doing setsid() is this: you're not allowed to do
> it if you're already a process group leader. silent_mode worked by
> having postmaster do another fork, exit in the parent, and do setsid()
> in the child.

Hmph.  Can't we just ignore that error?

regards, tom lane



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Andrew Gierth
> "Tom" == Tom Lane  writes:

 Tom> BTW, just thinking outside the box a bit --- perhaps the ideal
 Tom> behavior to address Michael's use-case would be to have the
 Tom> postmaster itself do setsid(), but not until it reaches the state
 Tom> of being ready to accept client connections.

 Tom> We'd likely need a switch to control that. If memory serves, there
 Tom> used to be such a switch, but we got rid of the postmaster's
 Tom> setsid call and the switch too. We probably should dig in the
 Tom> archives and review the reasoning about that.

The old silent_mode switch?

The tricky part about doing setsid() is this: you're not allowed to do
it if you're already a process group leader. silent_mode worked by
having postmaster do another fork, exit in the parent, and do setsid()
in the child.

If postmaster is launched from pg_ctl, then it won't be a group leader
unless pg_ctl made it one. But when it's run from the shell, it will be
if the shell does job control (the initial command of each shell job is
the group leader); if it's run from a service management process, then
it'll depend on what that process does.

-- 
Andrew (irc:RhodiumToad)



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Tom Lane
I wrote:
> Michael Paquier  writes:
>> Hmm.  This patch breaks a feature of pg_ctl that I am really fond of for
>> development.  When starting a node which enters in recovery, I sometimes
>> use Ctrl-C to stop pg_ctl, which automatically makes the started
>> Postgres instance to stop, and this saves more strokes.  With your 
>> patch, you don't get that anymore: when issuing Ctrl-C on pg_ctl then
>> the started instance still runs in the background.  I would be ready to
>> accept a patch which does not change the default behavior, and makes the
>> deamonization behavior activated only if an option switch is given by
>> the user, like -d/--daemon.  So I am -1 for what is proposed in its
>> current shape.

> Hmm, that seems like a pretty niche usage.  I don't object to having
> a switch to control this, but it seems to me that dissociating from
> the terminal is by far the more commonly wanted behavior and so
> ought to be the default.

BTW, just thinking outside the box a bit --- perhaps the ideal behavior
to address Michael's use-case would be to have the postmaster itself
do setsid(), but not until it reaches the state of being ready to
accept client connections.

We'd likely need a switch to control that.  If memory serves, there
used to be such a switch, but we got rid of the postmaster's setsid
call and the switch too.  We probably should dig in the archives and
review the reasoning about that.

I'm still of the opinion that dissociating from the terminal ought to
be the default.  On at least some platforms, that happens automatically
because the postmaster's stdin, stdout, and stderr have been redirected
away from the terminal.  If we don't do it on platforms where setsid()
is necessary, then we have a cross-platform behavioral difference,
which generally doesn't seem like a good thing.

regards, tom lane



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Tom Lane
Michael Paquier  writes:
> On Mon, Aug 06, 2018 at 12:11:26PM +0800, Paul Guo wrote:
>> Yes, if considering the case of starting postmaster manually, we can not
>> create
>> a new session in postmaster, so pg_ctl seems to be a good place for setsid()
>> call. Attached a newer patch. Thanks.

> Hmm.  This patch breaks a feature of pg_ctl that I am really fond of for
> development.  When starting a node which enters in recovery, I sometimes
> use Ctrl-C to stop pg_ctl, which automatically makes the started
> Postgres instance to stop, and this saves more strokes.  With your 
> patch, you don't get that anymore: when issuing Ctrl-C on pg_ctl then
> the started instance still runs in the background.  I would be ready to
> accept a patch which does not change the default behavior, and makes the
> deamonization behavior activated only if an option switch is given by
> the user, like -d/--daemon.  So I am -1 for what is proposed in its
> current shape.

Hmm, that seems like a pretty niche usage.  I don't object to having
a switch to control this, but it seems to me that dissociating from
the terminal is by far the more commonly wanted behavior and so
ought to be the default.

regards, tom lane



Re: [Patch] Create a new session in postmaster by calling setsid()

2018-09-12 Thread Michael Paquier
On Mon, Aug 06, 2018 at 12:11:26PM +0800, Paul Guo wrote:
> Yes, if considering the case of starting postmaster manually, we can not
> create
> a new session in postmaster, so pg_ctl seems to be a good place for setsid()
> call. Attached a newer patch. Thanks.

Hmm.  This patch breaks a feature of pg_ctl that I am really fond of for
development.  When starting a node which enters in recovery, I sometimes
use Ctrl-C to stop pg_ctl, which automatically makes the started
Postgres instance to stop, and this saves more strokes.  With your 
patch, you don't get that anymore: when issuing Ctrl-C on pg_ctl then
the started instance still runs in the background.  I would be ready to
accept a patch which does not change the default behavior, and makes the
deamonization behavior activated only if an option switch is given by
the user, like -d/--daemon.  So I am -1 for what is proposed in its
current shape.
--
Michael


signature.asc
Description: PGP signature


Re: [Patch] Create a new session in postmaster by calling setsid()

2018-08-07 Thread Paul Guo
On Thu, Aug 2, 2018 at 10:30 PM, Tom Lane  wrote:

> Paul Guo  writes:
> > [ make the postmaster execute setsid() too ]
>
> I'm a bit skeptical of this proposal.  Forcing the postmaster to
> dissociate from its controlling terminal is a good thing in some
> scenarios, but probably less good in others, and manual postmaster
> starts are probably mostly in the latter class.
>
> I wonder whether having "pg_ctl start" do a setsid() would accomplish
> the same result with less chance of breaking debugging usages.
>
> regards, tom lane
>

Yes, if considering the case of starting postmaster manually, we can not
create
a new session in postmaster, so pg_ctl seems to be a good place for setsid()
call. Attached a newer patch. Thanks.


0001-Create-a-new-session-for-postmaster-in-pg_ctl-by-cal.patch
Description: Binary data


Re: [Patch] Create a new session in postmaster by calling setsid()

2018-08-02 Thread Tom Lane
Paul Guo  writes:
> [ make the postmaster execute setsid() too ]

I'm a bit skeptical of this proposal.  Forcing the postmaster to
dissociate from its controlling terminal is a good thing in some
scenarios, but probably less good in others, and manual postmaster
starts are probably mostly in the latter class.

I wonder whether having "pg_ctl start" do a setsid() would accomplish
the same result with less chance of breaking debugging usages.

regards, tom lane



[Patch] Create a new session in postmaster by calling setsid()

2018-08-01 Thread Paul Guo
Hello,

Recently I encountered an issue during testing and rootcaused it as the
title mentioned.

postmaster children have done this (creating a new session) by calling
InitPostmasterChild(),
but postmaster itself does not. This could lead to some issues (e..g signal
handling). The test script below is a simple example.

$ cat test.sh
pg_ctl -D ./data -l stop.log stop
sleep 2 -- wait for pg down.
pg_ctl -D ./data -l start.log start
sleep 2 -- wait for pg up.
echo "pg_sleep()-ing"
psql -d postgres -c 'select pg_sleep(1000)'  -- press ctrl+c, then you will
see postmaster and its children are all gone.

Long ago PG has pmdaemonize() to daemonize postmaster which of course
create a new session. That code was removed in the patch below.

commit f7ea6beaf4ca02b8e6dc576255e35a5b86035cb9
Author: Heikki Linnakangas 
Date:   Mon Jul 4 14:35:44 2011 +0300

Remove silent_mode. You get the same functionality with "pg_ctl -l
postmaster.log", or nohup.

There was a small issue with LINUX_OOM_ADJ and silent_mode, namely that
with
silent_mode the postmaster process incorrectly used the OOM settings
meant
for backend processes. We certainly could've fixed that directly, but
since
silent_mode was redundant anyway, we might as well just remove it.

Here is the related discussion about the patch. It seems that is related to
oom score setting in fork_process().
https://www.postgresql.org/message-id/4E046EA5.8070101%40enterprisedb.com

Personally I still like pg being a daemon, but probably I do not know some
real cases which do not like daemon. If we do not go back to pgdaemonize()
with further fix of fork_process() (assume I understand correctly) we could
simply call setsid() in postmaster code to fix the issue above. I added a
simple a patch as attached.

Thanks.


0001-Create-a-new-session-in-postmaster-by-calling-setsid.patch
Description: Binary data