@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $ PostgreSQL : pgsql / src / backend / utils / init / miscinit . c , v 1.176 2009 / 08 / 12 20 : 53 : 30 tgl Exp $
* $ PostgreSQL : pgsql / src / backend / utils / init / miscinit . c , v 1.177 2009 / 08 / 27 16 : 59 : 38 tgl Exp $
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
@ -683,7 +683,46 @@ CreateLockFile(const char *filename, bool amPostmaster,
int len ;
int encoded_pid ;
pid_t other_pid ;
pid_t my_pid = getpid ( ) ;
pid_t my_pid ,
my_p_pid ,
my_gp_pid ;
const char * envvar ;
/*
* If the PID in the lockfile is our own PID or our parent ' s or
* grandparent ' s PID , then the file must be stale ( probably left over from
* a previous system boot cycle ) . We need to check this because of the
* likelihood that a reboot will assign exactly the same PID as we had in
* the previous reboot , or one that ' s only one or two counts larger and
* hence the lockfile ' s PID now refers to an ancestor shell process . We
* allow pg_ctl to pass down its parent shell PID ( our grandparent PID )
* via the environment variable PG_GRANDPARENT_PID ; this is so that
* launching the postmaster via pg_ctl can be just as reliable as
* launching it directly . There is no provision for detecting
* further - removed ancestor processes , but if the init script is written
* carefully then all but the immediate parent shell will be root - owned
* processes and so the kill test will fail with EPERM . Note that we
* cannot get a false negative this way , because an existing postmaster
* would surely never launch a competing postmaster or pg_ctl process
* directly .
*/
my_pid = getpid ( ) ;
# ifndef WIN32
my_p_pid = getppid ( ) ;
# else
/*
* Windows hasn ' t got getppid ( ) , but doesn ' t need it since it ' s not
* using real kill ( ) either . . .
*/
my_p_pid = 0 ;
# endif
envvar = getenv ( " PG_GRANDPARENT_PID " ) ;
if ( envvar )
my_gp_pid = atoi ( envvar ) ;
else
my_gp_pid = 0 ;
/*
* We need a loop here because of race conditions . But don ' t loop forever
@ -745,17 +784,11 @@ CreateLockFile(const char *filename, bool amPostmaster,
/*
* Check to see if the other process still exists
*
* If the PID in the lockfile is our own PID or our parent ' s PID , then
* the file must be stale ( probably left over from a previous system
* boot cycle ) . We need this test because of the likelihood that a
* reboot will assign exactly the same PID as we had in the previous
* reboot . Also , if there is just one more process launch in this
* reboot than in the previous one , the lockfile might mention our
* parent ' s PID . We can reject that since we ' d never be launched
* directly by a competing postmaster . We can ' t detect grandparent
* processes unfortunately , but if the init script is written
* carefully then all but the immediate parent shell will be
* root - owned processes and so the kill test will fail with EPERM .
* Per discussion above , my_pid , my_p_pid , and my_gp_pid can be
* ignored as false matches .
*
* Normally kill ( ) will fail with ESRCH if the given PID doesn ' t
* exist .
*
* We can treat the EPERM - error case as okay because that error
* implies that the existing process has a different userid than we
@ -772,18 +805,9 @@ CreateLockFile(const char *filename, bool amPostmaster,
* Unix socket file belonging to an instance of Postgres being run by
* someone else , at least on machines where / tmp hasn ' t got a
* stickybit . )
*
* Windows hasn ' t got getppid ( ) , but doesn ' t need it since it ' s not
* using real kill ( ) either . . .
*
* Normally kill ( ) will fail with ESRCH if the given PID doesn ' t
* exist .
*/
if ( other_pid ! = my_pid
# ifndef WIN32
& & other_pid ! = getppid ( )
# endif
)
if ( other_pid ! = my_pid & & other_pid ! = my_p_pid & &
other_pid ! = my_gp_pid )
{
if ( kill ( other_pid , 0 ) = = 0 | |
( errno ! = ESRCH & & errno ! = EPERM ) )