PostgreSQL Source Code git master
Loading...
Searching...
No Matches
stack_depth.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * stack_depth.c
4 * Functions for monitoring and limiting process stack depth
5 *
6 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
8 *
9 *
10 * IDENTIFICATION
11 * src/backend/utils/misc/stack_depth.c
12 *
13 *-------------------------------------------------------------------------
14 */
15
16#include "postgres.h"
17
18#include <limits.h>
19#include <sys/resource.h>
20
21#include "miscadmin.h"
22#include "utils/guc_hooks.h"
23
24
25/* GUC variable for maximum stack depth (measured in kilobytes) */
27
28/* max_stack_depth converted to bytes for speed of checking */
30
31/*
32 * Stack base pointer -- initialized by set_stack_base(), which
33 * should be called from main().
34 */
35static char *stack_base_ptr = NULL;
36
37
38/*
39 * set_stack_base: set up reference point for stack depth checking
40 *
41 * Returns the old reference point, if any.
42 */
45{
46#ifndef HAVE__BUILTIN_FRAME_ADDRESS
47 char stack_base;
48#endif
50
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. This is also important
57 * with address sanitizer, see comment in stack_is_too_deep().
58 */
59#ifdef HAVE__BUILTIN_FRAME_ADDRESS
61#else
63#endif
64
65 return old;
66}
67
68/*
69 * restore_stack_base: restore reference point for stack depth checking
70 *
71 * This can be used after set_stack_base() to restore the old value. This
72 * is currently only used in PL/Java. When PL/Java calls a backend function
73 * from different thread, the thread's stack is at a different location than
74 * the main thread's stack, so it sets the base pointer before the call, and
75 * restores it afterwards.
76 */
77void
82
83
84/*
85 * check_stack_depth/stack_is_too_deep: check for excessively deep recursion
86 *
87 * This should be called someplace in any recursive routine that might possibly
88 * recurse deep enough to overflow the stack. Most Unixen treat stack
89 * overflow as an unrecoverable SIGSEGV, so we want to error out ourselves
90 * before hitting the hardware limit.
91 *
92 * check_stack_depth() just throws an error summarily. stack_is_too_deep()
93 * can be used by code that wants to handle the error condition itself.
94 */
95void
97{
99 {
102 errmsg("stack depth limit exceeded"),
103 errhint("Increase the configuration parameter \"max_stack_depth\" (currently %dkB), "
104 "after ensuring the platform's stack depth limit is adequate.",
106 }
107}
108
109bool
111{
112#ifndef HAVE__BUILTIN_FRAME_ADDRESS
113 char stack_top_loc;
114#endif
116 char *stack_address;
117
118 /*
119 * With address sanitizer's stack-use-after-return check, stack variables
120 * are moved to heap allocations, to allow to detect references to the
121 * memory at a later time. That would break our stack-depth check. Luckily
122 * __builtin_frame_address() works correctly, even under asan.
123 */
124#ifndef HAVE__BUILTIN_FRAME_ADDRESS
126#else
128#endif
129
130 /*
131 * Compute distance from reference point to my stack frame.
132 */
134
135 /*
136 * Take abs value, since stacks grow up on some machines, down on others
137 */
138 if (stack_depth < 0)
140
141 /*
142 * Trouble?
143 *
144 * The test on stack_base_ptr prevents us from erroring out if called
145 * before that's been set. Logically it should be done first, but putting
146 * it last avoids wasting cycles during normal cases.
147 */
150 return true;
151
152 return false;
153}
154
155
156/* GUC check hook for max_stack_depth */
157bool
159{
162
164 {
165 GUC_check_errdetail("\"max_stack_depth\" must not exceed %zdkB.",
166 (stack_rlimit - STACK_DEPTH_SLOP) / 1024);
167 GUC_check_errhint("Increase the platform's stack depth limit via \"ulimit -s\" or local equivalent.");
168 return false;
169 }
170 return true;
171}
172
173/* GUC assign hook for max_stack_depth */
174void
181
182/*
183 * Obtain platform stack depth limit (in bytes)
184 *
185 * Return -1 if unknown
186 *
187 * Note: we choose to use ssize_t not size_t as the result type because
188 * callers compute values that could theoretically go negative,
189 * such as "result - STACK_DEPTH_SLOP".
190 */
193{
194#if defined(HAVE_GETRLIMIT)
195 static ssize_t val = 0;
196
197 /* This won't change after process launch, so check just once */
198 if (val == 0)
199 {
200 struct rlimit rlim;
201
202 if (getrlimit(RLIMIT_STACK, &rlim) < 0)
203 val = -1;
204 else if (rlim.rlim_cur == RLIM_INFINITY)
205 val = SSIZE_MAX;
206 /* rlim_cur is probably of an unsigned type, so check for overflow */
207 else if (rlim.rlim_cur >= SSIZE_MAX)
208 val = SSIZE_MAX;
209 else
210 val = rlim.rlim_cur;
211 }
212 return val;
213#else
214 /* On Windows we set the backend stack size in src/backend/Makefile */
215 return WIN32_STACK_RLIMIT;
216#endif
217}
int errcode(int sqlerrcode)
Definition elog.c:875
int errhint(const char *fmt,...) pg_attribute_printf(1
#define ERROR
Definition elog.h:40
#define ereport(elevel,...)
Definition elog.h:152
#define newval
#define GUC_check_errdetail
Definition guc.h:507
GucSource
Definition guc.h:112
#define GUC_check_errhint
Definition guc.h:511
long val
Definition informix.c:689
#define STACK_DEPTH_SLOP
Definition miscadmin.h:300
char * pg_stack_base_t
Definition miscadmin.h:302
static char * errmsg
static rewind_source * source
Definition pg_rewind.c:89
static int fb(int x)
void restore_stack_base(pg_stack_base_t base)
Definition stack_depth.c:78
int max_stack_depth
Definition stack_depth.c:26
ssize_t get_stack_depth_rlimit(void)
bool check_max_stack_depth(int *newval, void **extra, GucSource source)
bool stack_is_too_deep(void)
void assign_max_stack_depth(int newval, void *extra)
static char * stack_base_ptr
Definition stack_depth.c:35
static ssize_t max_stack_depth_bytes
Definition stack_depth.c:29
void check_stack_depth(void)
Definition stack_depth.c:96
pg_stack_base_t set_stack_base(void)
Definition stack_depth.c:44