Skip to content

Commit c8196c8

Browse files
committed
Adjust postmaster to recognize that a lockfile containing its parent's PID
must be stale. Tweak example startup scripts to not use pg_ctl but launch the postmaster directly, thereby ensuring that only the postmaster's direct parent shell will be a postgres-owned process. In combination these should fix the longstanding problem of the postmaster sometimes refusing to start during reboot because it thinks the old lockfile is not stale.
1 parent 8bbfa16 commit c8196c8

File tree

4 files changed

+72
-37
lines changed

4 files changed

+72
-37
lines changed

contrib/start-scripts/PostgreSQL.darwin

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ prefix="/usr/local/pgsql"
4848
# Data directory
4949
PGDATA="/usr/local/pgsql/data"
5050

51-
# Who to run pg_ctl as, should be "postgres".
51+
# Who to run the postmaster as, usually "postgres". (NOT "root")
5252
PGUSER="postgres"
5353

5454
# the logfile path and name (NEEDS to be writeable by PGUSER)
@@ -68,8 +68,13 @@ ROTATESEC="604800"
6868
# The path that is to be used for the script
6969
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
7070

71-
# What to use to start up the postmaster
72-
DAEMON="$prefix/bin/pg_ctl"
71+
# What to use to start up the postmaster (we do NOT use pg_ctl for this,
72+
# as it adds no value and can cause the postmaster to misrecognize a stale
73+
# lock file)
74+
DAEMON="$prefix/bin/postmaster"
75+
76+
# What to use to shut down the postmaster
77+
PGCTL="$prefix/bin/pg_ctl"
7378

7479
# The apache log rotation utility
7580
LOGUTIL="/usr/sbin/rotatelogs"
@@ -80,27 +85,28 @@ StartService () {
8085
if [ "${POSTGRESQLSERVER:=-NO-}" = "-YES-" ]; then
8186
ConsoleMessage "Starting PostgreSQL database server"
8287
if [ "${ROTATELOGS}" = "1" ]; then
83-
sudo -u $PGUSER sh -c "${DAEMON} start -D ${PGDATA} -s | ${LOGUTIL} ${PGLOG} ${ROTATESEC} &"
88+
sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' | ${LOGUTIL} '${PGLOG}' ${ROTATESEC} &"
8489
else
85-
sudo -u $PGUSER $DAEMON start -D "$PGDATA" -s -l $PGLOG
90+
sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' &" >>$PGLOG 2>&1
8691
fi
8792
fi
8893
}
8994

9095
StopService () {
9196
ConsoleMessage "Stopping PostgreSQL database server"
92-
sudo -u $PGUSER $DAEMON stop -D "$PGDATA" -s -m fast
97+
sudo -u $PGUSER $PGCTL stop -D "$PGDATA" -s -m fast
9398
}
9499

95100
RestartService () {
96101
if [ "${POSTGRESQLSERVER:=-NO-}" = "-YES-" ]; then
97102
ConsoleMessage "Restarting PostgreSQL database server"
103+
# should match StopService:
104+
sudo -u $PGUSER $PGCTL stop -D "$PGDATA" -s -m fast
105+
# should match StartService:
98106
if [ "${ROTATELOGS}" = "1" ]; then
99-
# StopService
100-
# StartService
101-
sudo -u $PGUSER sh -c "${DAEMON} restart -D ${PGDATA} -s -m fast | ${LOGUTIL} ${PGLOG} ${ROTATESEC} &"
107+
sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' | ${LOGUTIL} '${PGLOG}' ${ROTATESEC} &"
102108
else
103-
sudo -u $PGUSER $DAEMON restart -D "$PGDATA" -s -m fast
109+
sudo -u $PGUSER sh -c "${DAEMON} -D '${PGDATA}' &" >>$PGLOG 2>&1
104110
fi
105111
else
106112
StopService

contrib/start-scripts/freebsd

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
# Created through merger of the Linux start script by Ryan Kirkpatrick
77
# and the script in the FreeBSD ports collection.
88

9-
# $PostgreSQL: pgsql/contrib/start-scripts/freebsd,v 1.3 2003/11/29 19:51:35 pgsql Exp $
9+
# $PostgreSQL: pgsql/contrib/start-scripts/freebsd,v 1.4 2004/10/01 18:30:21 tgl Exp $
1010

1111
## EDIT FROM HERE
1212

@@ -16,7 +16,7 @@ prefix=/usr/local/pgsql
1616
# Data directory
1717
PGDATA="/usr/local/pgsql/data"
1818

19-
# Who to run pg_ctl as, should be "postgres".
19+
# Who to run the postmaster as, usually "postgres". (NOT "root")
2020
PGUSER=postgres
2121

2222
# Where to keep a log file
@@ -27,24 +27,31 @@ PGLOG="$PGDATA/serverlog"
2727
# The path that is to be used for the script
2828
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
2929

30-
# What to use to start up the postmaster
31-
DAEMON="$prefix/bin/pg_ctl"
30+
# What to use to start up the postmaster (we do NOT use pg_ctl for this,
31+
# as it adds no value and can cause the postmaster to misrecognize a stale
32+
# lock file)
33+
DAEMON="$prefix/bin/postmaster"
3234

35+
# What to use to shut down the postmaster
36+
PGCTL="$prefix/bin/pg_ctl"
37+
38+
# Only start if we can find the postmaster.
3339
test -x "$DAEMON" || exit 0
3440

3541
case $1 in
3642
start)
37-
su -l $PGUSER -c "$DAEMON start -D '$PGDATA' -s -l $PGLOG"
43+
su -l $PGUSER -c "$DAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
3844
echo -n ' postgresql'
3945
;;
4046
stop)
41-
su -l $PGUSER -c "$DAEMON stop -D '$PGDATA' -s -m fast"
47+
su -l $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast"
4248
;;
4349
restart)
44-
su -l $PGUSER -c "$DAEMON restart -D '$PGDATA' -s -m fast"
50+
su -l $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast -w"
51+
su -l $PGUSER -c "$DAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
4552
;;
4653
status)
47-
su -l $PGUSER -c "$DAEMON status -D '$PGDATA'"
54+
su -l $PGUSER -c "$PGCTL status -D '$PGDATA'"
4855
;;
4956
*)
5057
# Print help

contrib/start-scripts/linux

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
# Original author: Ryan Kirkpatrick <pgsql@rkirkpat.net>
2626

27-
# $PostgreSQL: pgsql/contrib/start-scripts/linux,v 1.6 2003/11/29 19:51:36 pgsql Exp $
27+
# $PostgreSQL: pgsql/contrib/start-scripts/linux,v 1.7 2004/10/01 18:30:21 tgl Exp $
2828

2929
## EDIT FROM HERE
3030

@@ -34,7 +34,7 @@ prefix=/usr/local/pgsql
3434
# Data directory
3535
PGDATA="/usr/local/pgsql/data"
3636

37-
# Who to run pg_ctl as, should be "postgres".
37+
# Who to run the postmaster as, usually "postgres". (NOT "root")
3838
PGUSER=postgres
3939

4040
# Where to keep a log file
@@ -54,38 +54,44 @@ fi
5454
# The path that is to be used for the script
5555
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
5656

57-
# What to use to start up the postmaster
58-
DAEMON="$prefix/bin/pg_ctl"
57+
# What to use to start up the postmaster (we do NOT use pg_ctl for this,
58+
# as it adds no value and can cause the postmaster to misrecognize a stale
59+
# lock file)
60+
DAEMON="$prefix/bin/postmaster"
61+
62+
# What to use to shut down the postmaster
63+
PGCTL="$prefix/bin/pg_ctl"
5964

6065
set -e
6166

62-
# Only start if we can find pg_ctl.
63-
test -f $DAEMON || exit 0
67+
# Only start if we can find the postmaster.
68+
test -x $DAEMON || exit 0
6469

6570
# Parse command line parameters.
6671
case $1 in
6772
start)
6873
$ECHO_N "Starting PostgreSQL: "$ECHO_C
69-
su - $PGUSER -c "$DAEMON start -D '$PGDATA' -s -l $PGLOG"
74+
su - $PGUSER -c "$DAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
7075
echo "ok"
7176
;;
7277
stop)
7378
echo -n "Stopping PostgreSQL: "
74-
su - $PGUSER -c "$DAEMON stop -D '$PGDATA' -s -m fast"
79+
su - $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast"
7580
echo "ok"
7681
;;
7782
restart)
7883
echo -n "Restarting PostgreSQL: "
79-
su - $PGUSER -c "$DAEMON restart -D '$PGDATA' -s -m fast -l $PGLOG"
84+
su - $PGUSER -c "$PGCTL stop -D '$PGDATA' -s -m fast -w"
85+
su - $PGUSER -c "$DAEMON -D '$PGDATA' &" >>$PGLOG 2>&1
8086
echo "ok"
8187
;;
8288
reload)
8389
echo -n "Reload PostgreSQL: "
84-
su - $PGUSER -c "$DAEMON reload -D '$PGDATA' -s"
90+
su - $PGUSER -c "$PGCTL reload -D '$PGDATA' -s"
8591
echo "ok"
8692
;;
8793
status)
88-
su - $PGUSER -c "$DAEMON status -D '$PGDATA'"
94+
su - $PGUSER -c "$PGCTL status -D '$PGDATA'"
8995
;;
9096
*)
9197
# Print help

src/backend/utils/init/miscinit.c

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.132 2004/08/29 05:06:50 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/utils/init/miscinit.c,v 1.133 2004/10/01 18:30:25 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -526,10 +526,22 @@ CreateLockFile(const char *filename, bool amPostmaster,
526526
/*
527527
* Check to see if the other process still exists
528528
*
529+
* If the PID in the lockfile is our own PID or our parent's PID,
530+
* then the file must be stale (probably left over from a previous
531+
* system boot cycle). We need this test because of the likelihood
532+
* that a reboot will assign exactly the same PID as we had in the
533+
* previous reboot. Also, if there is just one more process launch
534+
* in this reboot than in the previous one, the lockfile might mention
535+
* our parent's PID. We can reject that since we'd never be launched
536+
* directly by a competing postmaster. We can't detect grandparent
537+
* processes unfortunately, but if the init script is written carefully
538+
* then all but the immediate parent shell will be root-owned processes
539+
* and so the kill test will fail with EPERM.
540+
*
529541
* Normally kill() will fail with ESRCH if the given PID doesn't
530542
* exist. BeOS returns EINVAL for some silly reason, however.
531543
*/
532-
if (other_pid != my_pid)
544+
if (other_pid != my_pid && other_pid != getppid())
533545
{
534546
if (kill(other_pid, 0) == 0 ||
535547
(errno != ESRCH
@@ -544,12 +556,16 @@ CreateLockFile(const char *filename, bool amPostmaster,
544556
errmsg("lock file \"%s\" already exists",
545557
filename),
546558
isDDLock ?
547-
errhint("Is another %s (PID %d) running in data directory \"%s\"?",
548-
(encoded_pid < 0 ? "postgres" : "postmaster"),
549-
(int) other_pid, refName) :
550-
errhint("Is another %s (PID %d) using socket file \"%s\"?",
551-
(encoded_pid < 0 ? "postgres" : "postmaster"),
552-
(int) other_pid, refName)));
559+
(encoded_pid < 0 ?
560+
errhint("Is another postgres (PID %d) running in data directory \"%s\"?",
561+
(int) other_pid, refName) :
562+
errhint("Is another postmaster (PID %d) running in data directory \"%s\"?",
563+
(int) other_pid, refName)) :
564+
(encoded_pid < 0 ?
565+
errhint("Is another postgres (PID %d) using socket file \"%s\"?",
566+
(int) other_pid, refName) :
567+
errhint("Is another postmaster (PID %d) using socket file \"%s\"?",
568+
(int) other_pid, refName))));
553569
}
554570
}
555571

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy