From 792b0f4666b6ea6346aa8d29b568e5d3fe1fcef5 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Wed, 29 Nov 2000 20:59:54 +0000 Subject: [PATCH] Get rid of not-very-portable fcntl(F_SETLK) mechanism for locking the Unix socket file, in favor of having an ordinary lockfile beside the socket file. Clean up a few robustness problems in the lockfile code. If postmaster is going to reject a connection request based on database state, it will now tell you so before authentication exchange not after. (Of course, a failure after is still possible if conditions change meanwhile, but this makes life easier for a yet-to-be-written pg_ping utility.) --- configure | 282 +++++++++----------- configure.in | 17 -- src/backend/libpq/pqcomm.c | 75 ++---- src/backend/postmaster/postmaster.c | 236 ++++++++-------- src/backend/tcop/postgres.c | 16 +- src/backend/utils/init/miscinit.c | 400 +++++++++++++++------------- src/backend/utils/misc/guc.c | 4 +- src/bin/pg_ctl/pg_ctl.sh | 12 +- src/include/config.h.in | 5 +- src/include/miscadmin.h | 17 +- 10 files changed, 498 insertions(+), 566 deletions(-) diff --git a/configure b/configure index ad9434bb20..668eabfd73 100755 --- a/configure +++ b/configure @@ -2641,7 +2641,7 @@ INSTALL_SHLIB="\${INSTALL} $INSTL_SHLIB_OPTS" -for ac_prog in gawk mawk nawk awk +for ac_prog in mawk gawk nawk awk do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -5557,49 +5557,15 @@ EOF fi -echo $ac_n "checking for fcntl(F_SETLK)""... $ac_c" 1>&6 -echo "configure:5562: checking for fcntl(F_SETLK)" >&5 -case $host_os in - linux*) echo "$ac_t""broken on Linux" 1>&6 ;; - *) -cat > conftest.$ac_ext < -#include - -int main() { -struct flock lck; -lck.l_whence = SEEK_SET; lck.l_start = lck.l_len = 0; -lck.l_type = F_WRLCK; -fcntl(0, F_SETLK, &lck); -; return 0; } -EOF -if { (eval echo configure:5579: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then - rm -rf conftest* - cat >> confdefs.h <<\EOF -#define HAVE_FCNTL_SETLK 1 -EOF - echo "$ac_t""yes" 1>&6 -else - echo "configure: failed program was:" >&5 - cat conftest.$ac_ext >&5 - rm -rf conftest* - echo "$ac_t""no" 1>&6 -fi -rm -f conftest* - ;; -esac - for ac_func in fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5598: checking for $ac_func" >&5 +echo "configure:5564: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5648,12 +5614,12 @@ done echo $ac_n "checking for PS_STRINGS""... $ac_c" 1>&6 -echo "configure:5652: checking for PS_STRINGS" >&5 +echo "configure:5618: checking for PS_STRINGS" >&5 if eval "test \"`echo '$''{'pgac_cv_var_PS_STRINGS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -5663,7 +5629,7 @@ PS_STRINGS->ps_nargvstr = 1; PS_STRINGS->ps_argvstr = "foo"; ; return 0; } EOF -if { (eval echo configure:5667: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5633: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* pgac_cv_var_PS_STRINGS=yes else @@ -5685,12 +5651,12 @@ fi SNPRINTF='' echo $ac_n "checking for snprintf""... $ac_c" 1>&6 -echo "configure:5689: checking for snprintf" >&5 +echo "configure:5655: checking for snprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_snprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5683: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_snprintf=yes" else @@ -5737,12 +5703,12 @@ SNPRINTF='snprintf.o' fi echo $ac_n "checking for vsnprintf""... $ac_c" 1>&6 -echo "configure:5741: checking for vsnprintf" >&5 +echo "configure:5707: checking for vsnprintf" >&5 if eval "test \"`echo '$''{'ac_cv_func_vsnprintf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5735: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_vsnprintf=yes" else @@ -5790,7 +5756,7 @@ fi cat > conftest.$ac_ext < EOF @@ -5805,7 +5771,7 @@ fi rm -f conftest* cat > conftest.$ac_ext < EOF @@ -5822,12 +5788,12 @@ rm -f conftest* # do this one the hard way in case isinf() is a macro echo $ac_n "checking for isinf""... $ac_c" 1>&6 -echo "configure:5826: checking for isinf" >&5 +echo "configure:5792: checking for isinf" >&5 if eval "test \"`echo '$''{'ac_cv_func_isinf'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -5835,7 +5801,7 @@ int main() { double x = 0.0; int res = isinf(x); ; return 0; } EOF -if { (eval echo configure:5839: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5805: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_func_isinf=yes else @@ -5861,12 +5827,12 @@ else for ac_func in fpclass fp_class fp_class_d class do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:5865: checking for $ac_func" >&5 +echo "configure:5831: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5859: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -5917,12 +5883,12 @@ fi echo $ac_n "checking for getrusage""... $ac_c" 1>&6 -echo "configure:5921: checking for getrusage" >&5 +echo "configure:5887: checking for getrusage" >&5 if eval "test \"`echo '$''{'ac_cv_func_getrusage'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5915: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_getrusage=yes" else @@ -5970,12 +5936,12 @@ fi echo $ac_n "checking for srandom""... $ac_c" 1>&6 -echo "configure:5974: checking for srandom" >&5 +echo "configure:5940: checking for srandom" >&5 if eval "test \"`echo '$''{'ac_cv_func_srandom'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:5968: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_srandom=yes" else @@ -6023,12 +5989,12 @@ fi echo $ac_n "checking for gethostname""... $ac_c" 1>&6 -echo "configure:6027: checking for gethostname" >&5 +echo "configure:5993: checking for gethostname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6021: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostname=yes" else @@ -6076,12 +6042,12 @@ fi echo $ac_n "checking for random""... $ac_c" 1>&6 -echo "configure:6080: checking for random" >&5 +echo "configure:6046: checking for random" >&5 if eval "test \"`echo '$''{'ac_cv_func_random'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6074: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_random=yes" else @@ -6129,12 +6095,12 @@ fi echo $ac_n "checking for inet_aton""... $ac_c" 1>&6 -echo "configure:6133: checking for inet_aton" >&5 +echo "configure:6099: checking for inet_aton" >&5 if eval "test \"`echo '$''{'ac_cv_func_inet_aton'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6127: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_inet_aton=yes" else @@ -6182,12 +6148,12 @@ fi echo $ac_n "checking for strerror""... $ac_c" 1>&6 -echo "configure:6186: checking for strerror" >&5 +echo "configure:6152: checking for strerror" >&5 if eval "test \"`echo '$''{'ac_cv_func_strerror'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6180: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strerror=yes" else @@ -6236,12 +6202,12 @@ fi echo $ac_n "checking for strdup""... $ac_c" 1>&6 -echo "configure:6240: checking for strdup" >&5 +echo "configure:6206: checking for strdup" >&5 if eval "test \"`echo '$''{'ac_cv_func_strdup'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6234: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strdup=yes" else @@ -6289,12 +6255,12 @@ fi echo $ac_n "checking for strtol""... $ac_c" 1>&6 -echo "configure:6293: checking for strtol" >&5 +echo "configure:6259: checking for strtol" >&5 if eval "test \"`echo '$''{'ac_cv_func_strtol'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6287: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strtol=yes" else @@ -6342,12 +6308,12 @@ fi echo $ac_n "checking for strtoul""... $ac_c" 1>&6 -echo "configure:6346: checking for strtoul" >&5 +echo "configure:6312: checking for strtoul" >&5 if eval "test \"`echo '$''{'ac_cv_func_strtoul'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6340: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strtoul=yes" else @@ -6395,12 +6361,12 @@ fi echo $ac_n "checking for strcasecmp""... $ac_c" 1>&6 -echo "configure:6399: checking for strcasecmp" >&5 +echo "configure:6365: checking for strcasecmp" >&5 if eval "test \"`echo '$''{'ac_cv_func_strcasecmp'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6393: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_strcasecmp=yes" else @@ -6448,12 +6414,12 @@ fi echo $ac_n "checking for cbrt""... $ac_c" 1>&6 -echo "configure:6452: checking for cbrt" >&5 +echo "configure:6418: checking for cbrt" >&5 if eval "test \"`echo '$''{'ac_cv_func_cbrt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6446: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_cbrt=yes" else @@ -6497,7 +6463,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for cbrt in -lm""... $ac_c" 1>&6 -echo "configure:6501: checking for cbrt in -lm" >&5 +echo "configure:6467: checking for cbrt in -lm" >&5 ac_lib_var=`echo m'_'cbrt | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -6505,7 +6471,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lm $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6486: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6554,12 +6520,12 @@ esac echo $ac_n "checking for rint""... $ac_c" 1>&6 -echo "configure:6558: checking for rint" >&5 +echo "configure:6524: checking for rint" >&5 if eval "test \"`echo '$''{'ac_cv_func_rint'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6552: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_rint=yes" else @@ -6603,7 +6569,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for rint in -lm""... $ac_c" 1>&6 -echo "configure:6607: checking for rint in -lm" >&5 +echo "configure:6573: checking for rint in -lm" >&5 ac_lib_var=`echo m'_'rint | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -6611,7 +6577,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lm $HPUXMATHLIB $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6592: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -6651,9 +6617,9 @@ fi # Readline versions < 2.1 don't have rl_completion_append_character echo $ac_n "checking for rl_completion_append_character""... $ac_c" 1>&6 -echo "configure:6655: checking for rl_completion_append_character" >&5 +echo "configure:6621: checking for rl_completion_append_character" >&5 cat > conftest.$ac_ext < #ifdef HAVE_READLINE_H @@ -6666,7 +6632,7 @@ int main() { rl_completion_append_character = 'x'; ; return 0; } EOF -if { (eval echo configure:6670: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6636: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* echo "$ac_t""yes" 1>&6 cat >> confdefs.h <<\EOF @@ -6687,7 +6653,7 @@ rm -f conftest* # with earlier Cygwins don't have this declared, although it's in the # library. echo $ac_n "checking whether filename_completion_function is declared""... $ac_c" 1>&6 -echo "configure:6691: checking whether filename_completion_function is declared" >&5 +echo "configure:6657: checking whether filename_completion_function is declared" >&5 if test "$ac_cv_header_readline_h" = yes; then _readline_header='readline.h' elif test "$ac_cv_header_readline_readline_h" = yes; then @@ -6696,7 +6662,7 @@ else _readline_header='xxx' fi cat > conftest.$ac_ext < EOF @@ -6718,16 +6684,16 @@ rm -f conftest* echo $ac_n "checking for finite""... $ac_c" 1>&6 -echo "configure:6722: checking for finite" >&5 +echo "configure:6688: checking for finite" >&5 cat > conftest.$ac_ext < int main() { int dummy=finite(1.0); ; return 0; } EOF -if { (eval echo configure:6731: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6697: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_FINITE 1 @@ -6742,16 +6708,16 @@ fi rm -f conftest* echo $ac_n "checking for sigsetjmp""... $ac_c" 1>&6 -echo "configure:6746: checking for sigsetjmp" >&5 +echo "configure:6712: checking for sigsetjmp" >&5 cat > conftest.$ac_ext < int main() { sigjmp_buf x; sigsetjmp(x, 1); ; return 0; } EOF -if { (eval echo configure:6755: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6721: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* cat >> confdefs.h <<\EOF #define HAVE_SIGSETJMP 1 @@ -6771,12 +6737,12 @@ if test x"${enable_syslog+set}" = xset; then case $enable_syslog in yes) echo $ac_n "checking for syslog""... $ac_c" 1>&6 -echo "configure:6775: checking for syslog" >&5 +echo "configure:6741: checking for syslog" >&5 if eval "test \"`echo '$''{'ac_cv_func_syslog'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6769: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_syslog=yes" else @@ -6838,19 +6804,19 @@ fi echo $ac_n "checking for optreset""... $ac_c" 1>&6 -echo "configure:6842: checking for optreset" >&5 +echo "configure:6808: checking for optreset" >&5 if eval "test \"`echo '$''{'pgac_cv_var_int_optreset'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { extern int optreset; optreset = 1; ; return 0; } EOF -if { (eval echo configure:6854: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:6820: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* pgac_cv_var_int_optreset=yes else @@ -6873,7 +6839,7 @@ fi echo $ac_n "checking whether long int is 64 bits""... $ac_c" 1>&6 -echo "configure:6877: checking whether long int is 64 bits" >&5 +echo "configure:6843: checking whether long int is 64 bits" >&5 if eval "test \"`echo '$''{'pgac_cv_type_long_int_64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6882,7 +6848,7 @@ else echo "configure: warning: 64 bit arithmetic disabled when cross-compiling" 1>&2 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6881: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_type_long_int_64=yes else @@ -6938,7 +6904,7 @@ fi if test x"$HAVE_LONG_INT_64" = x"no" ; then echo $ac_n "checking whether long long int is 64 bits""... $ac_c" 1>&6 -echo "configure:6942: checking whether long long int is 64 bits" >&5 +echo "configure:6908: checking whether long long int is 64 bits" >&5 if eval "test \"`echo '$''{'pgac_cv_type_long_long_int_64'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -6947,7 +6913,7 @@ else echo "configure: warning: 64 bit arithmetic disabled when cross-compiling" 1>&2 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:6946: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_type_long_long_int_64=yes else @@ -7007,7 +6973,7 @@ fi if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then if [ x$SNPRINTF = x ] ; then echo $ac_n "checking whether snprintf handles 'long long int' as %lld""... $ac_c" 1>&6 -echo "configure:7011: checking whether snprintf handles 'long long int' as %lld" >&5 +echo "configure:6977: checking whether snprintf handles 'long long int' as %lld" >&5 if test "$cross_compiling" = yes; then echo "$ac_t""assuming not on target machine" 1>&6 # Force usage of our own snprintf, since we cannot test foreign snprintf @@ -7016,7 +6982,7 @@ echo "configure:7011: checking whether snprintf handles 'long long int' as %lld" else cat > conftest.$ac_ext < typedef long long int int64; @@ -7043,7 +7009,7 @@ main() { exit(! does_int64_snprintf_work()); } EOF -if { (eval echo configure:7047: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7013: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "$ac_t""yes" 1>&6 INT64_FORMAT='"%lld"' @@ -7054,7 +7020,7 @@ else rm -fr conftest* echo "$ac_t""no" 1>&6 echo $ac_n "checking whether snprintf handles 'long long int' as %qd""... $ac_c" 1>&6 -echo "configure:7058: checking whether snprintf handles 'long long int' as %qd" >&5 +echo "configure:7024: checking whether snprintf handles 'long long int' as %qd" >&5 if test "$cross_compiling" = yes; then echo "$ac_t""assuming not on target machine" 1>&6 # Force usage of our own snprintf, since we cannot test foreign snprintf @@ -7063,7 +7029,7 @@ echo "configure:7058: checking whether snprintf handles 'long long int' as %qd" else cat > conftest.$ac_ext < typedef long long int int64; @@ -7090,7 +7056,7 @@ main() { exit(! does_int64_snprintf_work()); } EOF -if { (eval echo configure:7094: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7060: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then echo "$ac_t""yes" 1>&6 INT64_FORMAT='"%qd"' @@ -7130,12 +7096,12 @@ EOF for ac_func in strtoll strtoq do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7134: checking for $ac_func" >&5 +echo "configure:7100: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7128: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7185,12 +7151,12 @@ done for ac_func in strtoull strtouq do echo $ac_n "checking for $ac_func""... $ac_c" 1>&6 -echo "configure:7189: checking for $ac_func" >&5 +echo "configure:7155: checking for $ac_func" >&5 if eval "test \"`echo '$''{'ac_cv_func_$ac_func'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7183: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_$ac_func=yes" else @@ -7241,7 +7207,7 @@ done echo $ac_n "checking alignment of short""... $ac_c" 1>&6 -echo "configure:7245: checking alignment of short" >&5 +echo "configure:7211: checking alignment of short" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7249,7 +7215,7 @@ else pgac_cv_alignof_short='sizeof(short)' else cat > conftest.$ac_ext < struct { char filler; short field; } mystruct; @@ -7261,7 +7227,7 @@ main() exit(0); } EOF -if { (eval echo configure:7265: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7231: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_short=`cat conftestval` else @@ -7281,7 +7247,7 @@ EOF echo $ac_n "checking alignment of int""... $ac_c" 1>&6 -echo "configure:7285: checking alignment of int" >&5 +echo "configure:7251: checking alignment of int" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7289,7 +7255,7 @@ else pgac_cv_alignof_int='sizeof(int)' else cat > conftest.$ac_ext < struct { char filler; int field; } mystruct; @@ -7301,7 +7267,7 @@ main() exit(0); } EOF -if { (eval echo configure:7305: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7271: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_int=`cat conftestval` else @@ -7321,7 +7287,7 @@ EOF echo $ac_n "checking alignment of long""... $ac_c" 1>&6 -echo "configure:7325: checking alignment of long" >&5 +echo "configure:7291: checking alignment of long" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7329,7 +7295,7 @@ else pgac_cv_alignof_long='sizeof(long)' else cat > conftest.$ac_ext < struct { char filler; long field; } mystruct; @@ -7341,7 +7307,7 @@ main() exit(0); } EOF -if { (eval echo configure:7345: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7311: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_long=`cat conftestval` else @@ -7362,7 +7328,7 @@ EOF if [ x"$HAVE_LONG_LONG_INT_64" = xyes ] ; then echo $ac_n "checking alignment of long long int""... $ac_c" 1>&6 -echo "configure:7366: checking alignment of long long int" >&5 +echo "configure:7332: checking alignment of long long int" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_long_long_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7370,7 +7336,7 @@ else pgac_cv_alignof_long_long_int='sizeof(long long int)' else cat > conftest.$ac_ext < struct { char filler; long long int field; } mystruct; @@ -7382,7 +7348,7 @@ main() exit(0); } EOF -if { (eval echo configure:7386: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7352: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_long_long_int=`cat conftestval` else @@ -7403,7 +7369,7 @@ EOF fi echo $ac_n "checking alignment of double""... $ac_c" 1>&6 -echo "configure:7407: checking alignment of double" >&5 +echo "configure:7373: checking alignment of double" >&5 if eval "test \"`echo '$''{'pgac_cv_alignof_double'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7411,7 +7377,7 @@ else pgac_cv_alignof_double='sizeof(double)' else cat > conftest.$ac_ext < struct { char filler; double field; } mystruct; @@ -7423,7 +7389,7 @@ main() exit(0); } EOF -if { (eval echo configure:7427: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:7393: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then pgac_cv_alignof_double=`cat conftestval` else @@ -7461,12 +7427,12 @@ EOF echo $ac_n "checking for POSIX signal interface""... $ac_c" 1>&6 -echo "configure:7465: checking for POSIX signal interface" >&5 +echo "configure:7431: checking for POSIX signal interface" >&5 if eval "test \"`echo '$''{'pgac_cv_func_posix_signals'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < @@ -7477,7 +7443,7 @@ act.sa_flags = SA_RESTART; sigaction(0, &act, &oact); ; return 0; } EOF -if { (eval echo configure:7481: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:7447: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* pgac_cv_func_posix_signals=yes else @@ -7507,7 +7473,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:7511: checking for $ac_word" >&5 +echo "configure:7477: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_TCLSH'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7543,7 +7509,7 @@ test -n "$TCLSH" && break done echo $ac_n "checking for tclConfig.sh""... $ac_c" 1>&6 -echo "configure:7547: checking for tclConfig.sh" >&5 +echo "configure:7513: checking for tclConfig.sh" >&5 # Let user override test if test -z "$TCL_CONFIG_SH"; then pgac_test_dirs="$with_tclconfig" @@ -7576,7 +7542,7 @@ fi # Check for Tk configuration script tkConfig.sh if test "$with_tk" = yes; then echo $ac_n "checking for tkConfig.sh""... $ac_c" 1>&6 -echo "configure:7580: checking for tkConfig.sh" >&5 +echo "configure:7546: checking for tkConfig.sh" >&5 # Let user override test if test -z "$TK_CONFIG_SH"; then pgac_test_dirs="$with_tkconfig $with_tclconfig" @@ -7615,7 +7581,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:7619: checking for $ac_word" >&5 +echo "configure:7585: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_NSGMLS'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7651,7 +7617,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:7655: checking for $ac_word" >&5 +echo "configure:7621: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_JADE'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7682,7 +7648,7 @@ done echo $ac_n "checking for DocBook V3.1""... $ac_c" 1>&6 -echo "configure:7686: checking for DocBook V3.1" >&5 +echo "configure:7652: checking for DocBook V3.1" >&5 if eval "test \"`echo '$''{'pgac_cv_check_docbook'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7715,7 +7681,7 @@ have_docbook=$pgac_cv_check_docbook echo $ac_n "checking for DocBook stylesheets""... $ac_c" 1>&6 -echo "configure:7719: checking for DocBook stylesheets" >&5 +echo "configure:7685: checking for DocBook stylesheets" >&5 if eval "test \"`echo '$''{'pgac_cv_path_stylesheets'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -7754,7 +7720,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:7758: checking for $ac_word" >&5 +echo "configure:7724: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_SGMLSPL'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else diff --git a/configure.in b/configure.in index da8ce513ee..a97567021f 100644 --- a/configure.in +++ b/configure.in @@ -758,23 +758,6 @@ PGAC_VAR_INT_TIMEZONE AC_FUNC_ACCEPT_ARGTYPES PGAC_FUNC_GETTIMEOFDAY_1ARG -AC_MSG_CHECKING([for fcntl(F_SETLK)]) -case $host_os in - linux*) AC_MSG_RESULT([broken on Linux]) ;; - *) -AC_TRY_LINK( -[#include -#include -], -[struct flock lck; -lck.l_whence = SEEK_SET; lck.l_start = lck.l_len = 0; -lck.l_type = F_WRLCK; -fcntl(0, F_SETLK, &lck);], -[AC_DEFINE(HAVE_FCNTL_SETLK) AC_MSG_RESULT(yes)], -[AC_MSG_RESULT(no)]) - ;; -esac - AC_CHECK_FUNCS([fcvt getopt_long memmove pstat setproctitle setsid sigprocmask sysconf waitpid dlopen]) AC_CACHE_CHECK([for PS_STRINGS], [pgac_cv_var_PS_STRINGS], diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index d680cfb7d5..35d6802a5a 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -29,7 +29,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: pqcomm.c,v 1.113 2000/11/21 23:03:53 petere Exp $ + * $Id: pqcomm.c,v 1.114 2000/11/29 20:59:51 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -169,7 +169,7 @@ StreamDoUnlink(void) /* * StreamServerPort -- open a sock stream "listening" port. * - * This initializes the Postmaster's connection-accepting port fdP. + * This initializes the Postmaster's connection-accepting port *fdP. * * RETURNS: STATUS_OK or STATUS_ERROR */ @@ -183,9 +183,6 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, err; size_t len = 0; int one = 1; -#ifdef HAVE_FCNTL_SETLK - int lock_fd; -#endif Assert(family == AF_INET || family == AF_UNIX); @@ -223,22 +220,15 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, len = UNIXSOCK_LEN(saddr.un); strcpy(sock_path, saddr.un.sun_path); /* - * If the socket exists but nobody has an advisory lock on it we - * can safely delete the file. + * Grab an interlock file associated with the socket file. */ -#ifdef HAVE_FCNTL_SETLK - if ((lock_fd = open(sock_path, O_WRONLY | O_NONBLOCK | PG_BINARY, 0666)) >= 0) - { - struct flock lck; - - lck.l_whence = SEEK_SET; - lck.l_start = lck.l_len = 0; - lck.l_type = F_WRLCK; - if (fcntl(lock_fd, F_SETLK, &lck) != -1) - unlink(sock_path); - close(lock_fd); - } -#endif /* HAVE_FCNTL_SETLK */ + if (! CreateSocketLockFile(sock_path, true)) + return STATUS_ERROR; + /* + * Once we have the interlock, we can safely delete any pre-existing + * socket file to avoid failure at bind() time. + */ + unlink(sock_path); } #endif /* HAVE_UNIX_SOCKETS */ @@ -274,8 +264,8 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, { snprintf(PQerrormsg, PQERRORMSG_LENGTH, "FATAL: StreamServerPort: bind() failed: %s\n" - "\tIs another postmaster already running on that port?\n", - strerror(errno)); + "\tIs another postmaster already running on port %d?\n", + strerror(errno), (int) portNumber); if (family == AF_UNIX) snprintf(PQerrormsg + strlen(PQerrormsg), PQERRORMSG_LENGTH - strlen(PQerrormsg), @@ -293,41 +283,14 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, #ifdef HAVE_UNIX_SOCKETS if (family == AF_UNIX) { + /* Arrange to unlink the socket file at exit */ on_proc_exit(StreamDoUnlink, 0); /* - * Open the socket file and get an advisory lock on it. The - * lock_fd is left open to keep the lock. + * Fix socket ownership/permission if requested. Note we must + * do this before we listen() to avoid a window where unwanted + * connections could get accepted. */ -#ifdef HAVE_FCNTL_SETLK - if ((lock_fd = open(sock_path, O_WRONLY | O_NONBLOCK | PG_BINARY, 0666)) >= 0) - { - struct flock lck; - - lck.l_whence = SEEK_SET; - lck.l_start = lck.l_len = 0; - lck.l_type = F_WRLCK; - if (fcntl(lock_fd, F_SETLK, &lck) != 0) - elog(DEBUG, "flock error on %s: %s", sock_path, strerror(errno)); - } -#endif /* HAVE_FCNTL_SETLK */ - } -#endif /* HAVE_UNIX_SOCKETS */ - - listen(fd, SOMAXCONN); - - /* - * MS: I took this code from Dillon's version. It makes the listening - * port non-blocking. That is not necessary (and may tickle kernel - * bugs). - * - * fcntl(fd, F_SETFD, 1); fcntl(fd, F_SETFL, FNDELAY); - */ - - *fdP = fd; - - if (family == AF_UNIX) - { Assert(Unix_socket_group); if (Unix_socket_group[0] != '\0') { @@ -379,6 +342,12 @@ StreamServerPort(int family, char *hostName, unsigned short portNumber, return STATUS_ERROR; } } +#endif /* HAVE_UNIX_SOCKETS */ + + listen(fd, SOMAXCONN); + + *fdP = fd; + return STATUS_OK; } diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 9fa4ebb368..80ff7bac3e 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.194 2000/11/28 23:27:55 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.195 2000/11/29 20:59:52 tgl Exp $ * * NOTES * @@ -104,8 +104,6 @@ typedef struct bkend long cancel_key; /* cancel key for cancels for this backend */ } Backend; -Port *MyBackendPort = NULL; - /* list of active backends. For garbage collection only now. */ static Dllist *BackendList; @@ -114,8 +112,8 @@ static Dllist *PortList; /* The socket number we are listening for connections on */ int PostPortNumber; -char * UnixSocketDir; -char * Virtual_host; +char *UnixSocketDir; +char *VirtualHost; /* * MaxBackends is the actual limit on the number of backends we will @@ -216,6 +214,7 @@ static int BackendStartup(Port *port); static int readStartupPacket(void *arg, PacketLen len, void *pkt); static int processCancelRequest(Port *port, PacketLen len, void *pkt); static int initMasks(fd_set *rmask, fd_set *wmask); +static char *canAcceptConnections(void); static long PostmasterRandom(void); static void RandomSalt(char *salt); static void SignalChildren(SIGNAL_ARGS); @@ -252,7 +251,7 @@ checkDataDir(const char *checkdir) "database system either by specifying the -D invocation " "option or by setting the PGDATA environment variable.\n\n", progname); - exit(2); + ExitPostmaster(2); } snprintf(path, sizeof(path), "%s%cglobal%cpg_control", @@ -265,7 +264,7 @@ checkDataDir(const char *checkdir) "\n\tExpected to find it in the PGDATA directory \"%s\"," "\n\tbut unable to open file \"%s\": %s\n\n", progname, checkdir, path, strerror(errno)); - exit(2); + ExitPostmaster(2); } FreeFile(fp); @@ -299,12 +298,12 @@ PostmasterMain(int argc, char *argv[]) if (strcmp(argv[1], "--help")==0 || strcmp(argv[1], "-?")==0) { usage(progname); - exit(0); + ExitPostmaster(0); } if (strcmp(argv[1], "--version")==0 || strcmp(argv[1], "-V")==0) { puts("postmaster (PostgreSQL) " PG_VERSION); - exit(0); + ExitPostmaster(0); } } @@ -367,7 +366,7 @@ PostmasterMain(int argc, char *argv[]) case '?': fprintf(stderr, "Try '%s --help' for more information.\n", progname); - exit(1); + ExitPostmaster(1); } } @@ -378,7 +377,7 @@ PostmasterMain(int argc, char *argv[]) { fprintf(stderr, "%s: invalid argument -- %s\n", progname, argv[optind]); fprintf(stderr, "Try '%s --help' for more information.\n", progname); - exit(1); + ExitPostmaster(1); } checkDataDir(potential_DataDir); /* issues error messages */ @@ -427,7 +426,7 @@ PostmasterMain(int argc, char *argv[]) enableFsync = false; break; case 'h': - Virtual_host = optarg; + VirtualHost = optarg; break; case 'i': NetServer = true; @@ -525,7 +524,7 @@ PostmasterMain(int argc, char *argv[]) default: /* shouldn't get here */ fprintf(stderr, "Try '%s --help' for more information.\n", progname); - exit(1); + ExitPostmaster(1); } } @@ -542,7 +541,7 @@ PostmasterMain(int argc, char *argv[]) */ fprintf(stderr, "%s: The number of buffers (-B) must be at least twice the number of allowed connections (-N) and at least 16.\n", progname); - exit(1); + ExitPostmaster(1); } if (DebugLvl > 2) @@ -558,6 +557,27 @@ PostmasterMain(int argc, char *argv[]) fprintf(stderr, "-----------------------------------------\n"); } + /* + * Fork away from controlling terminal, if -S specified. + * + * Must do this before we grab any interlock files, else the interlocks + * will show the wrong PID. + */ + if (SilentMode) + pmdaemonize(argc, argv); + + /* + * Create lockfile for data directory. + * + * We want to do this before we try to grab the input sockets, because + * the data directory interlock is more reliable than the socket-file + * interlock (thanks to whoever decided to put socket files in /tmp :-(). + * For the same reason, it's best to grab the TCP socket before the + * Unix socket. + */ + if (! CreateDataDirLockFile(DataDir, true)) + ExitPostmaster(1); + /* * Establish input sockets. */ @@ -566,7 +586,7 @@ PostmasterMain(int argc, char *argv[]) { fprintf(stderr, "%s: For SSL, TCP/IP connections must be enabled. See -? for help.\n", progname); - exit(1); + ExitPostmaster(1); } if (EnableSSL) InitSSL(); @@ -574,7 +594,7 @@ PostmasterMain(int argc, char *argv[]) if (NetServer) { - status = StreamServerPort(AF_INET, Virtual_host, + status = StreamServerPort(AF_INET, VirtualHost, (unsigned short) PostPortNumber, UnixSocketDir, &ServerSock_INET); if (status != STATUS_OK) @@ -586,7 +606,7 @@ PostmasterMain(int argc, char *argv[]) } #ifdef HAVE_UNIX_SOCKETS - status = StreamServerPort(AF_UNIX, Virtual_host, + status = StreamServerPort(AF_UNIX, VirtualHost, (unsigned short) PostPortNumber, UnixSocketDir, &ServerSock_UNIX); if (status != STATUS_OK) @@ -599,7 +619,9 @@ PostmasterMain(int argc, char *argv[]) XLOGPathInit(); - /* set up shared memory and semaphores */ + /* + * Set up shared memory and semaphores. + */ reset_shared(PostPortNumber); /* @@ -609,35 +631,12 @@ PostmasterMain(int argc, char *argv[]) BackendList = DLNewList(); PortList = DLNewList(); - if (SilentMode) - pmdaemonize(argc, argv); - else - { - - /* - * create pid file. if the file has already existed, exits. - */ - SetPidFname(DataDir); - if (SetPidFile(getpid()) == 0) - { - if (!CreateOptsFile(argc, argv)) - { - UnlinkPidFile(); - ExitPostmaster(1); - return 0; /* not reached */ - } - } - else - { - ExitPostmaster(1); - return 0; /* not reached */ - } - - /* - * register clean up proc - */ - on_proc_exit(UnlinkPidFile, 0); - } + /* + * Record postmaster options. We delay this till now to avoid recording + * bogus options (eg, NBuffers too high for available memory). + */ + if (!CreateOptsFile(argc, argv)) + ExitPostmaster(1); /* * Set up signal handlers for the postmaster process. @@ -658,11 +657,18 @@ PostmasterMain(int argc, char *argv[]) pqsignal(SIGTTOU, SIG_IGN); /* ignored */ pqsignal(SIGWINCH, dumpstatus); /* dump port status */ + /* + * We're ready to rock and roll... + */ StartupPID = StartupDataBase(); status = ServerLoop(); + /* + * ServerLoop probably shouldn't ever return, but if it does, close down. + */ ExitPostmaster(status != STATUS_OK); + return 0; /* not reached */ } @@ -672,8 +678,6 @@ pmdaemonize(int argc, char *argv[]) int i; pid_t pid; - SetPidFname(DataDir); - pid = fork(); if (pid == -1) { @@ -683,36 +687,8 @@ pmdaemonize(int argc, char *argv[]) } else if (pid) { /* parent */ - - /* - * create pid file. if the file has already existed, exits. - */ - if (SetPidFile(pid) == 0) - { - if (!CreateOptsFile(argc, argv)) - { - - /* - * Failed to create opts file. kill the child and exit - * now. - */ - UnlinkPidFile(); - kill(pid, SIGTERM); - ExitPostmaster(1); - return; /* not reached */ - } - _exit(0); - } - else - { - - /* - * Failed to create pid file. kill the child and exit now. - */ - kill(pid, SIGTERM); - ExitPostmaster(1); - return; /* not reached */ - } + /* Parent should just exit, without doing any atexit cleanup */ + _exit(0); } /* GH: If there's no setsid(), we hopefully don't need silent mode. @@ -723,7 +699,7 @@ pmdaemonize(int argc, char *argv[]) { fprintf(stderr, "%s: ", progname); perror("cannot disassociate from controlling TTY"); - exit(1); + ExitPostmaster(1); } #endif i = open(NULL_DEV, O_RDWR | PG_BINARY); @@ -731,11 +707,6 @@ pmdaemonize(int argc, char *argv[]) dup2(i, 1); dup2(i, 2); close(i); - - /* - * register clean up proc - */ - on_proc_exit(UnlinkPidFile, 0); } @@ -960,24 +931,19 @@ ServerLoop(void) if (status == STATUS_OK && port->pktInfo.state == Idle) { - /* - * Can't start backend if max backend count is exceeded. + * Can we accept a connection now? * - * The same when data base is in startup/shutdown mode. + * Even though readStartupPacket() already checked, + * we have to check again in case conditions changed + * while negotiating authentication. */ - if (Shutdown > NoShutdown) - PacketSendError(&port->pktInfo, - "The Data Base System is shutting down"); - else if (StartupPID) - PacketSendError(&port->pktInfo, - "The Data Base System is starting up"); - else if (FatalError) - PacketSendError(&port->pktInfo, - "The Data Base System is in recovery mode"); - else if (CountChildren() >= MaxBackends) - PacketSendError(&port->pktInfo, - "Sorry, too many clients already"); + char *rejectMsg = canAcceptConnections(); + + if (rejectMsg != NULL) + { + PacketSendError(&port->pktInfo, rejectMsg); + } else { @@ -1066,6 +1032,7 @@ readStartupPacket(void *arg, PacketLen len, void *pkt) { Port *port; StartupPacket *si; + char *rejectMsg; port = (Port *) arg; si = (StartupPacket *) pkt; @@ -1158,6 +1125,19 @@ readStartupPacket(void *arg, PacketLen len, void *pkt) return STATUS_OK; /* don't close the connection yet */ } + /* + * If we're going to reject the connection due to database state, + * say so now instead of wasting cycles on an authentication exchange. + * (This also allows a pg_ping utility to be written.) + */ + rejectMsg = canAcceptConnections(); + + if (rejectMsg != NULL) + { + PacketSendError(&port->pktInfo, rejectMsg); + return STATUS_OK; /* don't close the connection yet */ + } + /* Start the authentication itself. */ be_recvauth(port); @@ -1226,6 +1206,28 @@ processCancelRequest(Port *port, PacketLen len, void *pkt) return STATUS_ERROR; } +/* + * canAcceptConnections --- check to see if database state allows connections. + * + * If we are open for business, return NULL, otherwise return an error message + * string suitable for rejecting a connection request. + */ +static char * +canAcceptConnections(void) +{ + /* Can't start backends when in startup/shutdown/recovery state. */ + if (Shutdown > NoShutdown) + return "The Data Base System is shutting down"; + if (StartupPID) + return "The Data Base System is starting up"; + if (FatalError) + return "The Data Base System is in recovery mode"; + /* Can't start backend if max backend count is exceeded. */ + if (CountChildren() >= MaxBackends) + return "Sorry, too many clients already"; + + return NULL; +} /* * ConnCreate -- create a local connection data structure @@ -1423,7 +1425,7 @@ pmdie(SIGNAL_ARGS) } /* exit postmaster */ - proc_exit(0); + ExitPostmaster(0); } /* @@ -1465,9 +1467,9 @@ reaper(SIGNAL_ARGS) { fprintf(stderr, "Shutdown failed - abort\n"); fflush(stderr); - proc_exit(1); + ExitPostmaster(1); } - proc_exit(0); + ExitPostmaster(0); } if (StartupPID > 0) { @@ -1477,7 +1479,7 @@ reaper(SIGNAL_ARGS) { fprintf(stderr, "Startup failed - abort\n"); fflush(stderr); - proc_exit(1); + ExitPostmaster(1); } StartupPID = 0; FatalError = false; @@ -1507,7 +1509,7 @@ reaper(SIGNAL_ARGS) { /* - * Wait for all children exit then StartupDataBase. + * Wait for all children exit, then reset shmem and StartupDataBase. */ if (DLGetHead(BackendList)) return; @@ -1518,8 +1520,10 @@ reaper(SIGNAL_ARGS) "Reinitializing shared memory and semaphores\n", ctime(&tnow)); fflush(stderr); + shmem_exit(0); reset_shared(PostPortNumber); + StartupPID = StartupDataBase(); return; } @@ -1744,10 +1748,10 @@ BackendStartup(Port *port) { fprintf(stderr, "%s child[%d]: BackendStartup: backend startup failed\n", progname, (int) getpid()); - exit(1); + ExitPostmaster(1); } else - exit(0); + ExitPostmaster(0); } /* in parent */ @@ -1943,9 +1947,9 @@ DoBackend(Port *port) /* * Release postmaster's working memory context so that backend can - * recycle the space. Note we couldn't do it earlier than here, - * because port pointer is pointing into that space! But now we - * have copied all the interesting info into safe local storage. + * recycle the space. Note this does not trash *MyProcPort, because + * ConnCreate() allocated that space with malloc() ... else we'd need + * to copy the Port data here. */ MemoryContextSwitchTo(TopMemoryContext); MemoryContextDelete(PostmasterContext); @@ -1968,6 +1972,8 @@ DoBackend(Port *port) /* * ExitPostmaster -- cleanup + * + * Do NOT call exit() directly --- always go through here! */ static void ExitPostmaster(int status) @@ -2099,24 +2105,24 @@ InitSSL(void) if (!SSL_context) { fprintf(stderr, "Failed to create SSL context: %s\n", ERR_reason_error_string(ERR_get_error())); - exit(1); + ExitPostmaster(1); } snprintf(fnbuf, sizeof(fnbuf), "%s/server.crt", DataDir); if (!SSL_CTX_use_certificate_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) { fprintf(stderr, "Failed to load server certificate (%s): %s\n", fnbuf, ERR_reason_error_string(ERR_get_error())); - exit(1); + ExitPostmaster(1); } snprintf(fnbuf, sizeof(fnbuf), "%s/server.key", DataDir); if (!SSL_CTX_use_PrivateKey_file(SSL_context, fnbuf, SSL_FILETYPE_PEM)) { fprintf(stderr, "Failed to load private key file (%s): %s\n", fnbuf, ERR_reason_error_string(ERR_get_error())); - exit(1); + ExitPostmaster(1); } if (!SSL_CTX_check_private_key(SSL_context)) { fprintf(stderr, "Check of private key failed: %s\n", ERR_reason_error_string(ERR_get_error())); - exit(1); + ExitPostmaster(1); } } @@ -2178,7 +2184,7 @@ SSDataBase(int xlop) PG_SETMASK(&BlockSig); BootstrapMain(ac, av); - exit(0); + ExitPostmaster(0); } /* in parent */ diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 0f8dec00d8..7d143a9590 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.191 2000/11/25 20:33:52 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.192 2000/11/29 20:59:52 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1514,16 +1514,10 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha } /* - * Try to create pid file. + * Create lockfile for data directory. */ - SetPidFname(DataDir); - if (SetPidFile(-getpid())) - proc_exit(0); - - /* - * Register clean up proc. - */ - on_proc_exit(UnlinkPidFile, 0); + if (! CreateDataDirLockFile(DataDir, false)) + proc_exit(1); XLOGPathInit(); BaseInit(); @@ -1635,7 +1629,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[], const cha if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.191 $ $Date: 2000/11/25 20:33:52 $\n"); + puts("$Revision: 1.192 $ $Date: 2000/11/29 20:59:52 $\n"); } /* diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index 919a9dd220..98af889946 100644 --- a/src/backend/utils/init/miscinit.c +++ b/src/backend/utils/init/miscinit.c @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * miscinit.c - * miscellanious initialization support stuff + * miscellaneous initialization support stuff * * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.58 2000/11/17 01:24:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/init/miscinit.c,v 1.59 2000/11/29 20:59:53 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -32,8 +32,6 @@ #include "utils/builtins.h" #include "utils/syscache.h" -static char *GetPidFname(void); - #ifdef CYR_RECODE unsigned char RecodeForwTable[128]; @@ -43,6 +41,7 @@ unsigned char RecodeBackTable[128]; ProcessingMode Mode = InitProcessing; + /* ---------------------------------------------------------------- * ignoring system indexes support stuff * ---------------------------------------------------------------- @@ -99,10 +98,70 @@ SetDatabaseName(const char *name) } } -#ifndef MULTIBYTE -/* even if MULTIBYTE is not enabled, these functions are necessary - * since pg_proc.h has references to them. +/* + * Set data directory, but make sure it's an absolute path. Use this, + * never set DataDir directly. */ +void +SetDataDir(const char *dir) +{ + char *new; + + AssertArg(dir); + if (DataDir) + free(DataDir); + + if (dir[0] != '/') + { + char *buf; + size_t buflen; + + buflen = MAXPGPATH; + for (;;) + { + buf = malloc(buflen); + if (!buf) + elog(FATAL, "out of memory"); + + if (getcwd(buf, buflen)) + break; + else if (errno == ERANGE) + { + free(buf); + buflen *= 2; + continue; + } + else + { + free(buf); + elog(FATAL, "cannot get current working directory: %m"); + } + } + + new = malloc(strlen(buf) + 1 + strlen(dir) + 1); + sprintf(new, "%s/%s", buf, dir); + free(buf); + } + else + { + new = strdup(dir); + } + + if (!new) + elog(FATAL, "out of memory"); + DataDir = new; +} + + +/* ---------------------------------------------------------------- + * MULTIBYTE stub code + * + * Even if MULTIBYTE is not enabled, these functions are necessary + * since pg_proc.h has references to them. + * ---------------------------------------------------------------- + */ + +#ifndef MULTIBYTE Datum getdatabaseencoding(PG_FUNCTION_ARGS) @@ -124,7 +183,13 @@ PG_char_to_encoding(PG_FUNCTION_ARGS) #endif +/* ---------------------------------------------------------------- + * CYR_RECODE support + * ---------------------------------------------------------------- + */ + #ifdef CYR_RECODE + #define MAX_TOKEN 80 /* Some standard C libraries, including GNU, have an isblank() function. @@ -376,228 +441,189 @@ GetUserName(Oid userid) /*------------------------------------------------------------------------- - * Set data directory, but make sure it's an absolute path. Use this, - * never set DataDir directly. - *------------------------------------------------------------------------- - */ -void -SetDataDir(const char *dir) -{ - char *new; - - AssertArg(dir); - if (DataDir) - free(DataDir); - - if (dir[0] != '/') - { - char *buf; - size_t buflen; - - buflen = MAXPGPATH; - for (;;) - { - buf = malloc(buflen); - if (!buf) - elog(FATAL, "out of memory"); - - if (getcwd(buf, buflen)) - break; - else if (errno == ERANGE) - { - free(buf); - buflen *= 2; - continue; - } - else - { - free(buf); - elog(FATAL, "cannot get current working directory: %m"); - } - } - - new = malloc(strlen(buf) + 1 + strlen(dir) + 1); - sprintf(new, "%s/%s", buf, dir); - } - else - { - new = strdup(dir); - } - - if (!new) - elog(FATAL, "out of memory"); - DataDir = new; -} - - - -/*------------------------------------------------------------------------- + * Interlock-file support * - * postmaster pid file stuffs. $DATADIR/postmaster.pid is created when: + * These routines are used to create both a data-directory lockfile + * ($DATADIR/postmaster.pid) and a Unix-socket-file lockfile ($SOCKFILE.lock). + * Both kinds of files contain the same info: * - * (1) postmaster starts. In this case pid > 0. - * (2) postgres starts in standalone mode. In this case - * pid < 0 + * Owning process' PID + * Data directory path * - * to gain an interlock. - * - * SetPidFname(datadir) - * Remember the the pid file name. This is neccesary - * UnlinkPidFile() is called from proc_exit(). - * - * GetPidFname(datadir) - * Get the pid file name. SetPidFname() should be called - * before GetPidFname() gets called. - * - * UnlinkPidFile() - * This is called from proc_exit() and unlink the pid file. - * - * SetPidFile(pid_t pid) - * Create the pid file. On failure, it checks if the process - * actually exists or not. SetPidFname() should be called - * in prior to calling SetPidFile(). + * By convention, the owning process' PID is negated if it is a standalone + * backend rather than a postmaster. This is just for informational purposes. + * The path is also just for informational purposes (so that a socket lockfile + * can be more easily traced to the associated postmaster). * + * On successful lockfile creation, a proc_exit callback to remove the + * lockfile is automatically created. *------------------------------------------------------------------------- */ /* - * Path to pid file. proc_exit() remember it to unlink the file. + * proc_exit callback to remove a lockfile. */ -static char PidFile[MAXPGPATH]; - -/* - * Remove the pid file. This function is called from proc_exit. - */ -void -UnlinkPidFile(void) +static void +UnlinkLockFile(int status, Datum filename) { - unlink(PidFile); + unlink((char *) DatumGetPointer(filename)); + /* Should we complain if the unlink fails? */ } /* - * Set path to the pid file + * Create a lockfile, if possible + * + * Call CreateLockFile with the name of the lockfile to be created. If + * successful, it returns zero. On detecting a collision, it returns + * the PID or negated PID of the lockfile owner --- the caller is responsible + * for producing an appropriate error message. */ -void -SetPidFname(char *datadir) -{ - snprintf(PidFile, sizeof(PidFile), "%s/%s", datadir, PIDFNAME); -} - -/* - * Get path to the pid file - */ -static char * -GetPidFname(void) -{ - return (PidFile); -} - -/* - * Create the pid file - */ -int -SetPidFile(pid_t pid) +static int +CreateLockFile(const char *filename, bool amPostmaster) { int fd; - char *pidfile; - char pidstr[32]; + char buffer[MAXPGPATH + 32]; int len; - pid_t post_pid; - int is_postgres = 0; + int encoded_pid; + pid_t other_pid; + pid_t my_pid = getpid(); /* - * Creating pid file + * We need a loop here because of race conditions. */ - pidfile = GetPidFname(); - fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd < 0) + for (;;) { + /* + * Try to create the lock file --- O_EXCL makes this atomic. + */ + fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd >= 0) + break; /* Success; exit the retry loop */ + /* + * Couldn't create the pid file. Probably it already exists. + */ + if (errno != EEXIST && errno != EACCES) + elog(FATAL, "Can't create lock file %s: %m", filename); /* - * Couldn't create the pid file. Probably it already exists. Read - * the file to see if the process actually exists + * Read the file to get the old owner's PID. Note race condition + * here: file might have been deleted since we tried to create it. */ - fd = open(pidfile, O_RDONLY, 0600); + fd = open(filename, O_RDONLY, 0600); if (fd < 0) { - fprintf(stderr, "Can't open pid file: %s\n", pidfile); - fprintf(stderr, "Please check the permission and try again.\n"); - return (-1); - } - if ((len = read(fd, pidstr, sizeof(pidstr) - 1)) < 0) - { - fprintf(stderr, "Can't read pid file: %s\n", pidfile); - fprintf(stderr, "Please check the permission and try again.\n"); - close(fd); - return (-1); + if (errno == ENOENT) + continue; /* race condition; try again */ + elog(FATAL, "Can't read lock file %s: %m", filename); } + if ((len = read(fd, buffer, sizeof(buffer) - 1)) <= 0) + elog(FATAL, "Can't read lock file %s: %m", filename); close(fd); + buffer[len] = '\0'; + encoded_pid = atoi(buffer); + + /* if pid < 0, the pid is for postgres, not postmaster */ + other_pid = (pid_t) (encoded_pid < 0 ? -encoded_pid : encoded_pid); + + if (other_pid <= 0) + elog(FATAL, "Bogus data in lock file %s", filename); + /* - * Check to see if the process actually exists + * Check to see if the other process still exists */ - pidstr[len] = '\0'; - post_pid = (pid_t) atoi(pidstr); - - /* if pid < 0, the pid is for postgres, not postmatser */ - if (post_pid < 0) + if (other_pid != my_pid) { - is_postgres++; - post_pid = -post_pid; + if (kill(other_pid, 0) == 0 || + errno != ESRCH) + return encoded_pid; /* lockfile belongs to a live process */ } - if (post_pid == 0 || (post_pid > 0 && kill(post_pid, 0) < 0)) - { - - /* - * No, the process did not exist. Unlink the file and try to - * create it - */ - if (unlink(pidfile) < 0) - { - fprintf(stderr, "Can't remove pid file: %s\n", pidfile); - fprintf(stderr, "The file seems accidently left, but I couldn't remove it.\n"); - fprintf(stderr, "Please remove the file by hand and try again.\n"); - return (-1); - } - fd = open(pidfile, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd < 0) - { - fprintf(stderr, "Can't create pid file: %s\n", pidfile); - fprintf(stderr, "Please check the permission and try again.\n"); - return (-1); - } - } - else - { - - /* - * Another postmaster is running - */ - fprintf(stderr, "Can't create pid file: %s\n", pidfile); - if (is_postgres) - fprintf(stderr, "Is another postgres (pid: %d) running?\n", (int) post_pid); - else - fprintf(stderr, "Is another postmaster (pid: %s) running?\n", pidstr); - return (-1); - } + /* + * No, the process did not exist. Unlink the file and try again to + * create it. Need a loop because of possible race condition against + * other would-be creators. + */ + if (unlink(filename) < 0) + elog(FATAL, "Can't remove old lock file %s: %m" + "\n\tThe file seems accidentally left, but I couldn't remove it." + "\n\tPlease remove the file by hand and try again.", + filename); } - sprintf(pidstr, "%d", (int) pid); - if (write(fd, pidstr, strlen(pidstr)) != strlen(pidstr)) + /* + * Successfully created the file, now fill it. + */ + snprintf(buffer, sizeof(buffer), "%d\n%s\n", + amPostmaster ? (int) my_pid : - ((int) my_pid), + DataDir); + if (write(fd, buffer, strlen(buffer)) != strlen(buffer)) { - fprintf(stderr, "Write to pid file failed\n"); - fprintf(stderr, "Please check the permission and try again.\n"); + int save_errno = errno; + close(fd); - unlink(pidfile); - return (-1); + unlink(filename); + errno = save_errno; + elog(FATAL, "Can't write lock file %s: %m", filename); } close(fd); - return (0); + /* + * Arrange for automatic removal of lockfile at proc_exit. + */ + on_proc_exit(UnlinkLockFile, PointerGetDatum(strdup(filename))); + + return 0; /* Success! */ } +bool +CreateDataDirLockFile(const char *datadir, bool amPostmaster) +{ + char lockfile[MAXPGPATH]; + int encoded_pid; + snprintf(lockfile, sizeof(lockfile), "%s/postmaster.pid", datadir); + encoded_pid = CreateLockFile(lockfile, amPostmaster); + if (encoded_pid != 0) + { + fprintf(stderr, "Lock file \"%s\" already exists.\n", lockfile); + if (encoded_pid < 0) + fprintf(stderr, "Is another postgres (pid %d) running in \"%s\"?\n", + -encoded_pid, datadir); + else + fprintf(stderr, "Is another postmaster (pid %d) running in \"%s\"?\n", + encoded_pid, datadir); + return false; + } + return true; +} + +bool +CreateSocketLockFile(const char *socketfile, bool amPostmaster) +{ + char lockfile[MAXPGPATH]; + int encoded_pid; + + snprintf(lockfile, sizeof(lockfile), "%s.lock", socketfile); + encoded_pid = CreateLockFile(lockfile, amPostmaster); + if (encoded_pid != 0) + { + fprintf(stderr, "Lock file \"%s\" already exists.\n", lockfile); + if (encoded_pid < 0) + fprintf(stderr, "Is another postgres (pid %d) using \"%s\"?\n", + -encoded_pid, socketfile); + else + fprintf(stderr, "Is another postmaster (pid %d) using \"%s\"?\n", + encoded_pid, socketfile); + return false; + } + return true; +} + +/*------------------------------------------------------------------------- + * Version checking support + *------------------------------------------------------------------------- + */ /* * Determine whether the PG_VERSION file in directory `path' indicates @@ -628,12 +654,12 @@ ValidatePgVersion(const char *path) if (errno == ENOENT) elog(FATAL, "File %s is missing. This is not a valid data directory.", full_path); else - elog(FATAL, "cannot open %s: %s", full_path, strerror(errno)); + elog(FATAL, "cannot open %s: %m", full_path); } ret = fscanf(file, "%ld.%ld", &file_major, &file_minor); if (ret == EOF) - elog(FATAL, "cannot read %s: %s", full_path, strerror(errno)); + elog(FATAL, "cannot read %s: %m", full_path); else if (ret != 2) elog(FATAL, "`%s' does not have a valid format. You need to initdb.", full_path); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 7813b6d10b..398fb25bf6 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -4,7 +4,7 @@ * Support for grand unified configuration scheme, including SET * command, configuration file, and command line options. * - * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.23 2000/11/25 04:13:17 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.24 2000/11/29 20:59:53 tgl Exp $ * * Copyright 2000 by PostgreSQL Global Development Group * Written by Peter Eisentraut . @@ -319,7 +319,7 @@ ConfigureNamesString[] = {"unix_socket_directory", PGC_POSTMASTER, &UnixSocketDir, "", NULL}, - {"virtual_host", PGC_POSTMASTER, &Virtual_host, + {"virtual_host", PGC_POSTMASTER, &VirtualHost, "", NULL}, {NULL, 0, NULL, NULL, NULL} diff --git a/src/bin/pg_ctl/pg_ctl.sh b/src/bin/pg_ctl/pg_ctl.sh index ae7a1c19a0..6802269bef 100755 --- a/src/bin/pg_ctl/pg_ctl.sh +++ b/src/bin/pg_ctl/pg_ctl.sh @@ -8,7 +8,7 @@ # # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/bin/pg_ctl/Attic/pg_ctl.sh,v 1.15 2000/11/27 02:50:17 tgl Exp $ +# $Header: /cvsroot/pgsql/src/bin/pg_ctl/Attic/pg_ctl.sh,v 1.16 2000/11/29 20:59:53 tgl Exp $ # #------------------------------------------------------------------------- @@ -187,7 +187,7 @@ PIDFILE=$PGDATA/postmaster.pid if [ $op = "status" ];then if [ -f $PIDFILE ];then - PID=`cat $PIDFILE` + PID=`head -1 $PIDFILE` if [ $PID -lt 0 ];then PID=`expr 0 - $PID` echo "$CMDNAME: postgres is running (pid: $PID)" @@ -205,7 +205,7 @@ fi if [ $op = "stop" -o $op = "restart" ];then if [ -f $PIDFILE ];then - PID=`cat $PIDFILE` + PID=`head -1 $PIDFILE` if [ $PID -lt 0 ];then PID=`expr 0 - $PID` echo "$CMDNAME: Cannot restart postmaster. postgres is running (pid: $PID)" @@ -213,7 +213,7 @@ if [ $op = "stop" -o $op = "restart" ];then exit 1 fi - kill $sig `cat $PIDFILE` + kill $sig $PID # wait for postmaster shutting down if [ "$wait" = 1 -o $op = "restart" ];then @@ -253,7 +253,7 @@ fi if [ $op = "start" -o $op = "restart" ];then if [ -f $PIDFILE ];then echo "$CMDNAME: It seems another postmaster is running. Trying to start postmaster anyway." - pid=`cat $PIDFILE` + pid=`head -1 $PIDFILE` fi # no -o given @@ -275,7 +275,7 @@ if [ $op = "start" -o $op = "restart" ];then fi if [ -f $PIDFILE ];then - if [ "`cat $PIDFILE`" = "$pid" ];then + if [ "`head -1 $PIDFILE`" = "$pid" ];then echo "$CMDNAME: Cannot start postmaster. Is another postmaster is running?" exit 1 fi diff --git a/src/include/config.h.in b/src/include/config.h.in index ab699b30f3..1f6939dd96 100644 --- a/src/include/config.h.in +++ b/src/include/config.h.in @@ -8,7 +8,7 @@ * or in config.h afterwards. Of course, if you edit config.h, then your * changes will be overwritten the next time you run configure. * - * $Id: config.h.in,v 1.149 2000/11/20 16:52:54 petere Exp $ + * $Id: config.h.in,v 1.150 2000/11/29 20:59:54 tgl Exp $ */ #ifndef CONFIG_H @@ -567,9 +567,6 @@ extern void srandom(unsigned int seed); /* Set to 1 if you have struct sockaddr_un */ #undef HAVE_STRUCT_SOCKADDR_UN -/* Set to 1 if you have F_SETLK option for fcntl() */ -#undef HAVE_FCNTL_SETLK - /* Set to 1 if type "long int" works and is 64 bits */ #undef HAVE_LONG_INT_64 diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index cff6439dde..f41a01822a 100644 --- a/src/include/miscadmin.h +++ b/src/include/miscadmin.h @@ -12,7 +12,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: miscadmin.h,v 1.74 2000/11/25 22:34:13 momjian Exp $ + * $Id: miscadmin.h,v 1.75 2000/11/29 20:59:54 tgl Exp $ * * NOTES * some of the information in this file will be moved to @@ -114,7 +114,7 @@ extern int PostPortNumber; extern int Unix_socket_permissions; extern char *Unix_socket_group; extern char *UnixSocketDir; -extern char *Virtual_host; +extern char *VirtualHost; /***************************************************************************** @@ -227,17 +227,8 @@ extern bool IsIgnoringSystemIndexes(void); extern bool IsCacheInitialized(void); extern void SetWaitingForLock(bool); -/* - * "postmaster.pid" is a file containing postmaster's pid, being - * created uder $PGDATA upon postmaster's starting up. When postmaster - * shuts down, it will be unlinked. -*/ -#define PIDFNAME "postmaster.pid" - -extern void SetPidFname(char *datadir); -extern void UnlinkPidFile(void); -extern int SetPidFile(pid_t pid); - +extern bool CreateDataDirLockFile(const char *datadir, bool amPostmaster); +extern bool CreateSocketLockFile(const char *socketfile, bool amPostmaster); extern void ValidatePgVersion(const char *path);