We've had a couple of complaints in the past about recursive functions
crashing the server by overflowing the C execution stack. There is a
GUC variable max_expr_depth that is intended to prevent this sort of
problem for the particular case of overly complex arithmetic
expressions, but it's difficult to apply a similar solution to function
calls. A function nesting depth limit would necessarily be pretty
arbitrary, since different functions might use very different amounts of
stack space.
It occurred to me today that it would not be difficult to implement a
direct check on the physical size of the execution stack. We could have
PostgresMain do this:
/* global variables: */char *stack_base_ptr;int max_stack_size; /* settable through GUC */
PostgresMain(...){ char stack_base_loc;
stack_base_ptr = &stack_base_loc;
... server main loop here ...}
Then, in key recursive routines such as ExecQual, add a stack depth test
that looks like
void check_stack_depth(void){ char stack_top_loc;
if (abs(stack_base_ptr - &stack_top_loc) > max_stack_size) elog(ERROR, "Stack depth limit exceeded");}
Essentially we're measuring the distance between the local variables of
PostgresMain and those of the current recursive routine. (The abs()
operation is needed since the stack grows up on some machines and down
on others.)
Now, instead of a max_expr_depth variable that no one really knows how
to set intelligently, we have a max_stack_size variable that we can tell
people exactly how to set: a megabyte or so less than your "ulimit -s"
value should work fine for most cases. And it works for everything;
recursive function calls, whatever.
I imagine that somewhere in the fine print of the ANSI C standard, it
says that this maneuver doesn't give well-defined results --- but I
cannot think of any platform where it wouldn't work.
Comments?
regards, tom lane