diff --git a/configure b/configure index f37d2f6683..f01b03b15c 100755 --- a/configure +++ b/configure @@ -7589,7 +7589,8 @@ done -for ac_header in crypt.h dld.h endian.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/time.h sys/un.h termios.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h + +for ac_header in crypt.h dld.h endian.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/time.h sys/un.h termios.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h do as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` if eval "test \"\${$as_ac_Header+set}\" = set"; then @@ -13454,7 +13455,8 @@ fi -for ac_func in cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs + +for ac_func in cbrt dlopen fcvt fdatasync getpeereid getrlimit memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs do as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh` echo "$as_me:$LINENO: checking for $ac_func" >&5 diff --git a/configure.in b/configure.in index 5292146623..444ca1d8ff 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -dnl $PostgreSQL: pgsql/configure.in,v 1.481 2006/10/05 00:07:45 tgl Exp $ +dnl $PostgreSQL: pgsql/configure.in,v 1.482 2006/10/07 19:25:28 tgl Exp $ dnl dnl Developers, please strive to achieve this order: dnl @@ -717,7 +717,7 @@ fi ## dnl sys/socket.h is required by AC_FUNC_ACCEPT_ARGTYPES -AC_CHECK_HEADERS([crypt.h dld.h endian.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/time.h sys/un.h termios.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h]) +AC_CHECK_HEADERS([crypt.h dld.h endian.h fp_class.h getopt.h ieeefp.h langinfo.h poll.h pwd.h sys/ipc.h sys/poll.h sys/pstat.h sys/resource.h sys/select.h sys/sem.h sys/socket.h sys/shm.h sys/time.h sys/un.h termios.h utime.h wchar.h wctype.h kernel/OS.h kernel/image.h SupportDefs.h]) # At least on IRIX, cpp test for netinet/tcp.h will fail unless # netinet/in.h is included first. @@ -865,7 +865,7 @@ PGAC_VAR_INT_TIMEZONE AC_FUNC_ACCEPT_ARGTYPES PGAC_FUNC_GETTIMEOFDAY_1ARG -AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs]) +AC_CHECK_FUNCS([cbrt dlopen fcvt fdatasync getpeereid getrlimit memmove poll pstat readlink setproctitle setsid sigprocmask symlink sysconf towlower utime utimes waitpid wcstombs]) AC_CHECK_DECLS(fdatasync, [], [], [#include ]) AC_CHECK_DECLS(posix_fadvise, [], [], [#include ]) diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index 447e8487b0..3c15346e89 100644 --- a/contrib/pgbench/pgbench.c +++ b/contrib/pgbench/pgbench.c @@ -1,5 +1,5 @@ /* - * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.56 2006/10/04 00:29:45 momjian Exp $ + * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.57 2006/10/07 19:25:28 tgl Exp $ * * pgbench: a simple benchmark program for PostgreSQL * written by Tatsuo Ishii @@ -37,8 +37,9 @@ #include #endif -/* for getrlimit */ -#include +#ifdef HAVE_SYS_RESOURCE_H +#include /* for getrlimit */ +#endif #endif /* ! WIN32 */ extern char *optarg; @@ -1172,7 +1173,7 @@ main(int argc, char **argv) int nsocks; /* return from select(2) */ int maxsock; /* max socket number to be waited */ -#if !(defined(__CYGWIN__) || defined(__MINGW32__)) +#ifdef HAVE_GETRLIMIT struct rlimit rlim; #endif @@ -1233,8 +1234,8 @@ main(int argc, char **argv) fprintf(stderr, "invalid number of clients: %d\n", nclients); exit(1); } -#if !(defined(__CYGWIN__) || defined(__MINGW32__)) -#ifdef RLIMIT_NOFILE /* most platform uses RLIMIT_NOFILE */ +#ifdef HAVE_GETRLIMIT +#ifdef RLIMIT_NOFILE /* most platforms use RLIMIT_NOFILE */ if (getrlimit(RLIMIT_NOFILE, &rlim) == -1) #else /* but BSD doesn't ... */ if (getrlimit(RLIMIT_OFILE, &rlim) == -1) @@ -1245,11 +1246,11 @@ main(int argc, char **argv) } if (rlim.rlim_cur <= (nclients + 2)) { - fprintf(stderr, "You need at least %d open files resource but you are only allowed to use %ld.\n", nclients + 2, (long) rlim.rlim_cur); - fprintf(stderr, "Use limit/ulimt to increase the limit before using pgbench.\n"); + fprintf(stderr, "You need at least %d open files but you are only allowed to use %ld.\n", nclients + 2, (long) rlim.rlim_cur); + fprintf(stderr, "Use limit/ulimit to increase the limit before using pgbench.\n"); exit(1); } -#endif +#endif /* HAVE_GETRLIMIT */ break; case 'C': is_connect = 1; diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index b3223e3de4..549ca755d7 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ - + Server Configuration @@ -846,14 +846,22 @@ SET ENABLE_SEQSCAN TO OFF; equivalent), less a safety margin of a megabyte or so. The safety margin is needed because the stack depth is not checked in every routine in the server, but only in key potentially-recursive routines - such as expression evaluation. Setting the parameter higher than - the actual kernel limit will mean that a runaway recursive function - can crash an individual backend process. The default setting is + such as expression evaluation. The default setting is 2048 KB (two megabytes), which is conservatively small and unlikely to risk crashes. However, it may be too small to allow execution of complex functions. Only superusers can change this setting. + + + Setting max_stack_depth higher than + the actual kernel limit will mean that a runaway recursive function + can crash an individual backend process. On platforms where + PostgreSQL can determine the kernel limit, + it will not let you set this variable to an unsafe value. However, + not all platforms provide the information, so caution is recommended + in selecting a value. + @@ -2173,19 +2181,6 @@ SELECT * FROM parent WHERE key = 2400; - - gin_fuzzy_search_limit (integer) - - gin_fuzzy_search_limit configuration parameter - - - - Soft upper limit of the size of the set returned by GIN index. For more - information see . - - - - @@ -3718,6 +3713,19 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir' + + + gin_fuzzy_search_limit (integer) + + gin_fuzzy_search_limit configuration parameter + + + + Soft upper limit of the size of the set returned by GIN index. For more + information see . + + + local_preload_libraries (string) diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 9145904b49..ee63220d95 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.511 2006/10/07 16:43:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.512 2006/10/07 19:25:28 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -23,13 +23,20 @@ #include #include #include -#if HAVE_SYS_SELECT_H +#ifdef HAVE_SYS_SELECT_H #include #endif +#ifdef HAVE_SYS_RESOURCE_H +#include +#endif #ifdef HAVE_GETOPT_H #include #endif +#ifndef HAVE_GETRUSAGE +#include "rusagestub.h" +#endif + #include "access/printtup.h" #include "access/xact.h" #include "catalog/pg_type.h" @@ -78,7 +85,7 @@ bool Log_disconnections = false; LogStmtLevel log_statement = LOGSTMT_NONE; /* GUC variable for maximum stack depth (measured in kilobytes) */ -int max_stack_depth = 2048; +int max_stack_depth = 100; /* wait N seconds to allow attach from a debugger */ int PostAuthDelay = 0; @@ -91,7 +98,7 @@ int PostAuthDelay = 0; */ /* max_stack_depth converted to bytes for speed of checking */ -static long max_stack_depth_bytes = 2048 * 1024L; +static long max_stack_depth_bytes = 100 * 1024L; /* * Stack base pointer -- initialized by PostgresMain. This is not static @@ -2490,9 +2497,7 @@ ProcessInterrupts(void) * This should be called someplace in any recursive routine that might possibly * recurse deep enough to overflow the stack. Most Unixen treat stack * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves - * before hitting the hardware limit. Unfortunately we have no direct way - * to detect the hardware limit, so we have to rely on the admin to set a - * GUC variable for it ... + * before hitting the hardware limit. */ void check_stack_depth(void) @@ -2530,13 +2535,24 @@ check_stack_depth(void) } } -/* GUC assign hook to update max_stack_depth_bytes from max_stack_depth */ +/* GUC assign hook for max_stack_depth */ bool assign_max_stack_depth(int newval, bool doit, GucSource source) { - /* Range check was already handled by guc.c */ + long newval_bytes = newval * 1024L; + long stack_rlimit = get_stack_depth_rlimit(); + + if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP) + { + ereport((source >= PGC_S_INTERACTIVE) ? ERROR : LOG, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("\"max_stack_depth\" must not exceed %ldkB", + (stack_rlimit - STACK_DEPTH_SLOP) / 1024L), + errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent."))); + return false; + } if (doit) - max_stack_depth_bytes = newval * 1024L; + max_stack_depth_bytes = newval_bytes; return true; } @@ -3635,11 +3651,36 @@ PostgresMain(int argc, char *argv[], const char *username) return 1; /* keep compiler quiet */ } -#ifndef HAVE_GETRUSAGE -#include "rusagestub.h" -#else -#include -#endif /* HAVE_GETRUSAGE */ + +/* + * Obtain platform stack depth limit (in bytes) + * + * Return -1 if unlimited or not known + */ +long +get_stack_depth_rlimit(void) +{ +#if defined(HAVE_GETRLIMIT) && defined(RLIMIT_STACK) + static long val = 0; + + /* This won't change after process launch, so check just once */ + if (val == 0) + { + struct rlimit rlim; + + if (getrlimit(RLIMIT_STACK, &rlim) < 0) + val = -1; + else if (rlim.rlim_cur == RLIM_INFINITY) + val = -1; + else + val = rlim.rlim_cur; + } + return val; +#else /* no getrlimit */ + return -1; +#endif +} + static struct rusage Save_r; static struct timeval Save_t; diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 96244ec91f..d118755a3c 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut . * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.355 2006/10/06 17:14:00 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.356 2006/10/07 19:25:28 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -1214,7 +1214,7 @@ static struct config_int ConfigureNamesInt[] = GUC_UNIT_KB }, &max_stack_depth, - 2048, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL + 100, 100, MAX_KILOBYTES, assign_max_stack_depth, NULL }, { @@ -1610,7 +1610,7 @@ static struct config_int ConfigureNamesInt[] = }, { - {"gin_fuzzy_search_limit", PGC_USERSET, UNGROUPED, + {"gin_fuzzy_search_limit", PGC_USERSET, CLIENT_CONN_OTHER, gettext_noop("Sets the maximum allowed result for exact search by GIN."), NULL, 0 @@ -2702,6 +2702,7 @@ InitializeGUCOptions(void) { int i; char *env; + long stack_rlimit; /* * Build sorted array of all GUC variables. @@ -2839,6 +2840,27 @@ InitializeGUCOptions(void) env = getenv("PGCLIENTENCODING"); if (env != NULL) SetConfigOption("client_encoding", env, PGC_POSTMASTER, PGC_S_ENV_VAR); + + /* + * rlimit isn't exactly an "environment variable", but it behaves about + * the same. If we can identify the platform stack depth rlimit, increase + * default stack depth setting up to whatever is safe (but at most 2MB). + */ + stack_rlimit = get_stack_depth_rlimit(); + if (stack_rlimit > 0) + { + int new_limit = (stack_rlimit - STACK_DEPTH_SLOP) / 1024L; + + if (new_limit > 100) + { + char limbuf[16]; + + new_limit = Min(new_limit, 2048); + sprintf(limbuf, "%d", new_limit); + SetConfigOption("max_stack_depth", limbuf, + PGC_POSTMASTER, PGC_S_ENV_VAR); + } + } } diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in index c6fe887986..0043e9afaf 100644 --- a/src/include/pg_config.h.in +++ b/src/include/pg_config.h.in @@ -161,6 +161,9 @@ /* Define to 1 if you have the `getpwuid_r' function. */ #undef HAVE_GETPWUID_R +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + /* Define to 1 if you have the `getrusage' function. */ #undef HAVE_GETRUSAGE @@ -460,6 +463,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_PSTAT_H +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_RESOURCE_H + /* Define to 1 if you have the header file. */ #undef HAVE_SYS_SELECT_H diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h index e6637edeb7..2006b7c682 100644 --- a/src/include/tcop/tcopprot.h +++ b/src/include/tcop/tcopprot.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.84 2006/10/04 00:30:10 momjian Exp $ + * $PostgreSQL: pgsql/src/include/tcop/tcopprot.h,v 1.85 2006/10/07 19:25:29 tgl Exp $ * * OLD COMMENTS * This file was created so that other c files could get the two @@ -23,6 +23,9 @@ #include "utils/guc.h" +/* Required daylight between max_stack_depth and the kernel limit, in bytes */ +#define STACK_DEPTH_SLOP (512 * 1024L) + extern CommandDest whereToSendOutput; extern DLLIMPORT const char *debug_query_string; extern int max_stack_depth; @@ -62,6 +65,7 @@ extern void FloatExceptionHandler(SIGNAL_ARGS); extern void prepare_for_client_read(void); extern void client_read_ended(void); extern int PostgresMain(int argc, char *argv[], const char *username); +extern long get_stack_depth_rlimit(void); extern void ResetUsage(void); extern void ShowUsage(const char *title); extern int check_log_duration(char *msec_str, bool was_logged); diff --git a/src/include/utils/pg_rusage.h b/src/include/utils/pg_rusage.h index 32e409076e..bb11812da8 100644 --- a/src/include/utils/pg_rusage.h +++ b/src/include/utils/pg_rusage.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/pg_rusage.h,v 1.2 2006/03/05 15:59:07 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/pg_rusage.h,v 1.3 2006/10/07 19:25:29 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,7 +16,7 @@ #include -#ifdef HAVE_GETRUSAGE +#ifdef HAVE_SYS_RESOURCE_H #include #else #include "rusagestub.h"