aboutsummaryrefslogtreecommitdiff
path: root/src/backend/tcop/postgres.c
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-04-08 18:28:12 +0300
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2012-04-08 19:08:13 +0300
commitef29bb1f7254222835267cc03389ed12602c677c (patch)
tree985f3562c0a8de92789faf074bb3ff0eaa964111 /src/backend/tcop/postgres.c
parent63d8636c50f2ca053aa6a214340bb322bc5687d5 (diff)
downloadpostgresql-ef29bb1f7254222835267cc03389ed12602c677c.tar.gz
postgresql-ef29bb1f7254222835267cc03389ed12602c677c.zip
Do stack-depth checking in all postmaster children.
We used to only initialize the stack base pointer when starting up a regular backend, not in other processes. In particular, autovacuum workers can run arbitrary user code, and without stack-depth checking, infinite recursion in e.g an index expression will bring down the whole cluster. The comment about PL/Java using set_stack_base() is not yet true. As the code stands, PL/java still modifies the stack_base_ptr variable directly. However, it's been discussed in the PL/Java mailing list that it should be changed to use the function, because PL/Java is currently oblivious to the register stack used on Itanium. There's another issues with PL/Java, namely that the stack base pointer it sets is not really the base of the stack, it could be something close to the bottom of the stack. That's a separate issue that might need some further changes to this code, but that's a different story. Backpatch to all supported releases.
Diffstat (limited to 'src/backend/tcop/postgres.c')
-rw-r--r--src/backend/tcop/postgres.c61
1 files changed, 53 insertions, 8 deletions
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index 660a67412dc..638ba0fe066 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -114,8 +114,10 @@ int PostAuthDelay = 0;
static long max_stack_depth_bytes = 100 * 1024L;
/*
- * Stack base pointer -- initialized by PostgresMain. This is not static
- * so that PL/Java can modify it.
+ * Stack base pointer -- initialized by PostmasterMain and inherited by
+ * subprocesses. This is not static because old versions of PL/Java modify
+ * it directly. Newer versions use set_stack_base(), but we want to stay
+ * binary-compatible for the time being.
*/
char *stack_base_ptr = NULL;
@@ -3003,6 +3005,53 @@ ia64_get_bsp(void)
/*
+ * set_stack_base: set up reference point for stack depth checking
+ *
+ * Returns the old reference point, if any.
+ */
+pg_stack_base_t
+set_stack_base(void)
+{
+ char stack_base;
+ pg_stack_base_t old;
+
+#if defined(__ia64__) || defined(__ia64)
+ old.stack_base_ptr = stack_base_ptr;
+ old.register_stack_base_ptr = register_stack_base_ptr;
+#else
+ old = stack_base_ptr;
+#endif
+
+ /* Set up reference point for stack depth checking */
+ stack_base_ptr = &stack_base;
+#if defined(__ia64__) || defined(__ia64)
+ register_stack_base_ptr = ia64_get_bsp();
+#endif
+
+ return old;
+}
+
+/*
+ * restore_stack_base: restore reference point for stack depth checking
+ *
+ * This can be used after set_stack_base() to restore the old value. This
+ * is currently only used in PL/Java. When PL/Java calls a backend function
+ * from different thread, the thread's stack is at a different location than
+ * the main thread's stack, so it sets the base pointer before the call, and
+ * restores it afterwards.
+ */
+void
+restore_stack_base(pg_stack_base_t base)
+{
+#if defined(__ia64__) || defined(__ia64)
+ stack_base_ptr = base.stack_base_ptr;
+ register_stack_base_ptr = base.register_stack_base_ptr;
+#else
+ stack_base_ptr = base;
+#endif
+}
+
+/*
* check_stack_depth: check for excessively deep recursion
*
* This should be called someplace in any recursive routine that might possibly
@@ -3017,7 +3066,7 @@ check_stack_depth(void)
long stack_depth;
/*
- * Compute distance from PostgresMain's local variables to my own
+ * Compute distance from reference point to to my local variables
*/
stack_depth = (long) (stack_base_ptr - &stack_top_loc);
@@ -3459,7 +3508,6 @@ PostgresMain(int argc, char *argv[], const char *username)
{
const char *dbname;
int firstchar;
- char stack_base;
StringInfoData input_message;
sigjmp_buf local_sigjmp_buf;
volatile bool send_ready_for_query = true;
@@ -3486,10 +3534,7 @@ PostgresMain(int argc, char *argv[], const char *username)
SetProcessingMode(InitProcessing);
/* Set up reference point for stack depth checking */
- stack_base_ptr = &stack_base;
-#if defined(__ia64__) || defined(__ia64)
- register_stack_base_ptr = ia64_get_bsp();
-#endif
+ set_stack_base();
/* Compute paths, if we didn't inherit them from postmaster */
if (my_exec_path[0] == '\0')