diff --git a/configure b/configure
index f37d2f6683d9314fe547030dd9ffa6dbd3be9af5..f01b03b15c81fe3085e9e7d2e148c109620f7466 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 52921466235db1d4a21ecefb719c51d7f478177e..444ca1d8ff3ba42fe23e968d83cc2e51d45d08bb 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 <unistd.h>])
 AC_CHECK_DECLS(posix_fadvise, [], [], [#include <fcntl.h>])
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index 447e8487b0aab58e64cf2a1ee567cbe56782e7a1..3c15346e89902e11acda23189f10bb3144706de1 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 <sys/select.h>
 #endif
 
-/* for getrlimit */
-#include <sys/resource.h>
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>		/* 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 b3223e3de43a122486461f484211997809d02dcf..549ca755d70b21f36404e0a58816b82e8f4c131f 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.89 2006/09/25 22:12:24 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.90 2006/10/07 19:25:28 tgl Exp $ -->
 
 <chapter Id="runtime-config">
   <title>Server Configuration</title>
@@ -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.
        </para>
+
+       <para>
+        Setting <varname>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
+        <productname>PostgreSQL</productname> 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.
+       </para>
       </listitem>
      </varlistentry>
 
@@ -2173,19 +2181,6 @@ SELECT * FROM parent WHERE key = 2400;
       </listitem>
      </varlistentry>
 
-	 <varlistentry id="guc-gin-fuzzy-search-limit" xreflabel="gin_fuzzy_search_limit">
-	  <term><varname>gin_fuzzy_search_limit</varname> (<type>integer</type>)</term>
-	  <indexterm>
-	  <primary><varname>gin_fuzzy_search_limit</> configuration parameter</primary>
-	  </indexterm>
-	  <listitem>
-	   <para>
-		Soft upper limit of the size of the set returned by GIN index. For more
-		information see <xref linkend="gin-tips">.
-	   </para>
-	  </listitem>
-	 </varlistentry>
-	  
      </variablelist>
     </sect2>
    </sect1>
@@ -3718,6 +3713,19 @@ dynamic_library_path = 'C:\tools\postgresql;H:\my_project\lib;$libdir'
        </para>
       </listitem>
      </varlistentry>
+
+     <varlistentry id="guc-gin-fuzzy-search-limit" xreflabel="gin_fuzzy_search_limit">
+      <term><varname>gin_fuzzy_search_limit</varname> (<type>integer</type>)</term>
+      <indexterm>
+       <primary><varname>gin_fuzzy_search_limit</> configuration parameter</primary>
+      </indexterm>
+      <listitem>
+       <para>
+        Soft upper limit of the size of the set returned by GIN index. For more
+        information see <xref linkend="gin-tips">.
+       </para>
+      </listitem>
+     </varlistentry>
      
      <varlistentry id="guc-local-preload-libraries" xreflabel="local_preload_libraries">
       <term><varname>local_preload_libraries</varname> (<type>string</type>)</term>
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 9145904b49af37b6c7ff7bde40d33e204fbea7b8..ee63220d956a6b2e31ef94655fdfdc47d38bda98 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 <signal.h>
 #include <fcntl.h>
 #include <sys/socket.h>
-#if HAVE_SYS_SELECT_H
+#ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
 #ifdef HAVE_GETOPT_H
 #include <getopt.h>
 #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 <sys/resource.h>
-#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 96244ec91f8e87afcd32df395a98e6885a1ed905..d118755a3c364ae3e6ce96ce66a987960faf599c 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -10,7 +10,7 @@
  * Written by Peter Eisentraut <peter_e@gmx.net>.
  *
  * 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 c6fe8879868d69f79e58486fa667da4a869ba789..0043e9afaf2390e946fc9004f38d1361e785bfe3 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 <sys/pstat.h> header file. */
 #undef HAVE_SYS_PSTAT_H
 
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#undef HAVE_SYS_RESOURCE_H
+
 /* Define to 1 if you have the <sys/select.h> header file. */
 #undef HAVE_SYS_SELECT_H
 
diff --git a/src/include/tcop/tcopprot.h b/src/include/tcop/tcopprot.h
index e6637edeb7f4e34e26449bc6c80d0eac1c6d77aa..2006b7c6828d282bdd147fd6a34811b59a4110c8 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 32e409076e1560dc827be30a56d3a115e9f84aa6..bb11812da80bda980553e30b2ee4a3dafc8ad6bd 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 <sys/time.h>
 
-#ifdef HAVE_GETRUSAGE
+#ifdef HAVE_SYS_RESOURCE_H
 #include <sys/resource.h>
 #else
 #include "rusagestub.h"