PostgreSQL Source Code git master
stack_depth.c File Reference
#include "postgres.h"
#include <limits.h>
#include <sys/resource.h>
#include "miscadmin.h"
#include "utils/guc_hooks.h"
Include dependency graph for stack_depth.c:

Go to the source code of this file.

Functions

pg_stack_base_t set_stack_base (void)
 
void restore_stack_base (pg_stack_base_t base)
 
void check_stack_depth (void)
 
bool stack_is_too_deep (void)
 
bool check_max_stack_depth (int *newval, void **extra, GucSource source)
 
void assign_max_stack_depth (int newval, void *extra)
 
ssize_t get_stack_depth_rlimit (void)
 

Variables

int max_stack_depth = 100
 
static ssize_t max_stack_depth_bytes = 100 * (ssize_t) 1024
 
static char * stack_base_ptr = NULL
 

Function Documentation

◆ assign_max_stack_depth()

void assign_max_stack_depth ( int  newval,
void *  extra 
)

Definition at line 159 of file stack_depth.c.

160{
161 ssize_t newval_bytes = newval * (ssize_t) 1024;
162
163 max_stack_depth_bytes = newval_bytes;
164}
#define newval
static ssize_t max_stack_depth_bytes
Definition: stack_depth.c:29

References max_stack_depth_bytes, and newval.

◆ check_max_stack_depth()

bool check_max_stack_depth ( int *  newval,
void **  extra,
GucSource  source 
)

Definition at line 142 of file stack_depth.c.

143{
144 ssize_t newval_bytes = *newval * (ssize_t) 1024;
145 ssize_t stack_rlimit = get_stack_depth_rlimit();
146
147 if (stack_rlimit > 0 && newval_bytes > stack_rlimit - STACK_DEPTH_SLOP)
148 {
149 GUC_check_errdetail("\"max_stack_depth\" must not exceed %zdkB.",
150 (stack_rlimit - STACK_DEPTH_SLOP) / 1024);
151 GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent.");
152 return false;
153 }
154 return true;
155}
#define GUC_check_errdetail
Definition: guc.h:480
#define GUC_check_errhint
Definition: guc.h:484
#define STACK_DEPTH_SLOP
Definition: miscadmin.h:296
ssize_t get_stack_depth_rlimit(void)
Definition: stack_depth.c:176

References get_stack_depth_rlimit(), GUC_check_errdetail, GUC_check_errhint, newval, and STACK_DEPTH_SLOP.

◆ check_stack_depth()

void check_stack_depth ( void  )

Definition at line 95 of file stack_depth.c.

96{
98 {
100 (errcode(ERRCODE_STATEMENT_TOO_COMPLEX),
101 errmsg("stack depth limit exceeded"),
102 errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
103 "after ensuring the platform's stack depth limit is adequate.",
105 }
106}
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
int max_stack_depth
Definition: stack_depth.c:26
bool stack_is_too_deep(void)
Definition: stack_depth.c:109

References ereport, errcode(), errhint(), errmsg(), ERROR, max_stack_depth, and stack_is_too_deep().

Referenced by _jumbleNode(), AlterTypeRecurse(), apply_scanjoin_target_to_paths(), ATAddCheckNNConstraint(), ATExecAddColumn(), ATExecAlterConstrRecurse(), ATExecDropColumn(), ATExecSetNotNull(), CheckAttributeType(), checkCond(), clean_NOT_intree(), clean_stopword_intree(), cntsize(), contains_required_value(), convertJsonbValue(), copyObjectImpl(), Cover(), create_plan_recurse(), datum_to_json_internal(), datum_to_jsonb_internal(), dofindsubquery(), dropconstraint_internal(), emit_jsp_gin_entries(), equal(), eval_const_expressions_mutator(), EventTriggerInvoke(), ExecEndNode(), ExecEvalSubPlan(), ExecInitExprRec(), ExecInitNode(), ExecMakeFunctionResultSet(), ExecProcNodeFirst(), ExecShutdownNode_walker(), execute(), executeAnyItem(), executeBoolItem(), executeItemOptUnwrapTarget(), expand_partitioned_rtentry(), expression_tree_mutator_impl(), expression_tree_walker_impl(), extract_jsp_bool_expr(), fillQT(), find_composite_type_dependencies(), find_matching_subplans_recurse(), findDependentObjects(), findoprnd(), findoprnd_recurse(), flatten_grouping_sets(), flattenJsonPathParseItem(), FreePageManagerDumpBtree(), freetree(), generate_partition_qual(), generate_partitionwise_join_paths(), get_query_def(), get_rels_with_domain(), get_rule_expr(), get_setop_query(), get_steps_using_prefix_recurse(), gistSplit(), hash_range(), hash_range_extended(), hash_record(), hash_record_extended(), hk_depth_search(), infix(), inline_set_returning_function(), int_query_opr_selec(), is_simple_union_all_recurse(), JsonbDeepContains(), lseg_inside_poly(), ltree_execute(), makepol(), maketree(), MatchText(), MultiExecProcNode(), outNode(), p_ishost(), p_isURLPath(), parse_array(), parse_object(), parseNodeString(), plainnode(), planstate_tree_walker_impl(), plperl_hash_from_tuple(), plperl_sv_to_datum(), PLy_input_setup_func(), PLy_output_setup_func(), populate_array_dim_jsonb(), populate_record_field(), printJsonPathItem(), pull_up_sublinks_jointree_recurse(), pull_up_subqueries_recurse(), QT2QTN(), QTNBinary(), QTNClearFlags(), QTNCopy(), QTNFree(), QTNodeCompare(), QTNSort(), QTNTernary(), range_cmp(), range_in(), range_out(), range_recv(), range_send(), raw_expression_tree_walker_impl(), record_cmp(), record_eq(), record_in(), record_out(), record_recv(), record_send(), recurse_set_operations(), regex_selectivity_sub(), relation_is_updatable(), resolve_special_varno(), set_append_rel_size(), setPath(), split_array(), SplitToVariants(), standard_ProcessUtility(), transformExprRecurse(), transformFromClauseItem(), transformSetOperationTree(), traverse_lacons(), try_partitionwise_join(), TS_execute_locations_recurse(), TS_execute_recurse(), TS_phrase_execute(), tsquery_opr_selec(), and tsquery_requires_match().

◆ get_stack_depth_rlimit()

ssize_t get_stack_depth_rlimit ( void  )

Definition at line 176 of file stack_depth.c.

177{
178#if defined(HAVE_GETRLIMIT)
179 static ssize_t val = 0;
180
181 /* This won't change after process launch, so check just once */
182 if (val == 0)
183 {
184 struct rlimit rlim;
185
186 if (getrlimit(RLIMIT_STACK, &rlim) < 0)
187 val = -1;
188 else if (rlim.rlim_cur == RLIM_INFINITY)
189 val = SSIZE_MAX;
190 /* rlim_cur is probably of an unsigned type, so check for overflow */
191 else if (rlim.rlim_cur >= SSIZE_MAX)
192 val = SSIZE_MAX;
193 else
194 val = rlim.rlim_cur;
195 }
196 return val;
197#else
198 /* On Windows we set the backend stack size in src/backend/Makefile */
199 return WIN32_STACK_RLIMIT;
200#endif
201}
long val
Definition: informix.c:689

References val.

Referenced by check_max_stack_depth(), and InitializeGUCOptionsFromEnvironment().

◆ restore_stack_base()

void restore_stack_base ( pg_stack_base_t  base)

Definition at line 77 of file stack_depth.c.

78{
79 stack_base_ptr = base;
80}
static char * stack_base_ptr
Definition: stack_depth.c:35

References stack_base_ptr.

◆ set_stack_base()

pg_stack_base_t set_stack_base ( void  )

Definition at line 44 of file stack_depth.c.

45{
46#ifndef HAVE__BUILTIN_FRAME_ADDRESS
47 char stack_base;
48#endif
50
51 old = stack_base_ptr;
52
53 /*
54 * Set up reference point for stack depth checking. On recent gcc we use
55 * __builtin_frame_address() to avoid a warning about storing a local
56 * variable's address in a long-lived variable.
57 */
58#ifdef HAVE__BUILTIN_FRAME_ADDRESS
59 stack_base_ptr = __builtin_frame_address(0);
60#else
61 stack_base_ptr = &stack_base;
62#endif
63
64 return old;
65}
char * pg_stack_base_t
Definition: miscadmin.h:298

References stack_base_ptr.

Referenced by main().

◆ stack_is_too_deep()

bool stack_is_too_deep ( void  )

Definition at line 109 of file stack_depth.c.

110{
111 char stack_top_loc;
112 ssize_t stack_depth;
113
114 /*
115 * Compute distance from reference point to my local variables
116 */
117 stack_depth = (ssize_t) (stack_base_ptr - &stack_top_loc);
118
119 /*
120 * Take abs value, since stacks grow up on some machines, down on others
121 */
122 if (stack_depth < 0)
123 stack_depth = -stack_depth;
124
125 /*
126 * Trouble?
127 *
128 * The test on stack_base_ptr prevents us from erroring out if called
129 * before that's been set. Logically it should be done first, but putting
130 * it last avoids wasting cycles during normal cases.
131 */
132 if (stack_depth > max_stack_depth_bytes &&
133 stack_base_ptr != NULL)
134 return true;
135
136 return false;
137}

References max_stack_depth_bytes, and stack_base_ptr.

Referenced by check_stack_depth(), MemoryContextStatsInternal(), rstacktoodeep(), and ShowTransactionStateRec().

Variable Documentation

◆ max_stack_depth

int max_stack_depth = 100

Definition at line 26 of file stack_depth.c.

Referenced by check_stack_depth().

◆ max_stack_depth_bytes

ssize_t max_stack_depth_bytes = 100 * (ssize_t) 1024
static

Definition at line 29 of file stack_depth.c.

Referenced by assign_max_stack_depth(), and stack_is_too_deep().

◆ stack_base_ptr

char* stack_base_ptr = NULL
static

Definition at line 35 of file stack_depth.c.

Referenced by restore_stack_base(), set_stack_base(), and stack_is_too_deep().