</listitem>
</varlistentry>
+ <varlistentry id="guc-debug-assertions" xreflabel="debug_assertions">
+ <term><varname>debug_assertions</varname> (<type>boolean</type>)
+ <indexterm>
+ <primary><varname>debug_assertions</> configuration parameter</primary>
+ </indexterm>
+ </term>
+ <listitem>
+ <para>
+ Reports whether <productname>PostgreSQL</productname> has been built
+ with assertions enabled. That is the case if the
+ macro <symbol>USE_ASSERT_CHECKING</symbol> is defined
+ when <productname>PostgreSQL</productname> is built (accomplished
+ e.g. by the <command>configure</command> option
+ <option>--enable-cassert</option>). By
+ default <productname>PostgreSQL</productname> is built without
+ assertions.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry id="guc-integer-datetimes" xreflabel="integer_datetimes">
<term><varname>integer_datetimes</varname> (<type>boolean</type>)
<indexterm>
</listitem>
</varlistentry>
- <varlistentry id="guc-debug-assertions" xreflabel="debug_assertions">
- <term><varname>debug_assertions</varname> (<type>boolean</type>)
- <indexterm>
- <primary><varname>debug_assertions</> configuration parameter</primary>
- </indexterm>
- </term>
- <listitem>
- <para>
- Turns on various assertion checks. This is a debugging aid. If
- you are experiencing strange problems or crashes you might want
- to turn this on, as it might expose programming mistakes. To use
- this parameter, the macro <symbol>USE_ASSERT_CHECKING</symbol>
- must be defined when <productname>PostgreSQL</productname> is
- built (accomplished by the <command>configure</command> option
- <option>--enable-cassert</option>). Note that
- <varname>debug_assertions</varname> defaults to <literal>on</>
- if <productname>PostgreSQL</productname> has been built with
- assertions enabled.
- </para>
- </listitem>
- </varlistentry>
-
<varlistentry id="guc-ignore-system-indexes" xreflabel="ignore_system_indexes">
<term><varname>ignore_system_indexes</varname> (<type>boolean</type>)
<indexterm>
</thead>
<tbody>
- <row>
- <entry><option>-A <replaceable>x</replaceable></option></entry>
- <entry><literal>debug_assertions = <replaceable>x</replaceable></></entry>
- </row>
<row>
<entry><option>-B <replaceable>x</replaceable></option></entry>
<entry><literal>shared_buffers = <replaceable>x</replaceable></></entry>
<title>General Purpose</title>
<variablelist>
- <varlistentry>
- <term><option>-A 0|1</option></term>
- <listitem>
- <para>
- Enables run-time assertion checks, which is a debugging aid to
- detect programming mistakes. This option is only available if
- assertions were enabled when <productname>PostgreSQL</> was
- compiled. If so, the default is on.
- </para>
- </listitem>
- </varlistentry>
-
<varlistentry>
<term><option>-B <replaceable class="parameter">nbuffers</replaceable></option></term>
<listitem>
* Check that the encoded segment decodes back to the original items.
*/
#if defined (CHECK_ENCODING_ROUNDTRIP)
- if (assert_enabled)
{
int ndecoded;
ItemPointer tmp = ginPostingListDecode(result, &ndecoded);
* relevant command tag.
*/
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
{
const char *dbgtag;
* tcop/postgres.c (the option sets should not conflict) and with the
* common help() function in main/main.c.
*/
- while ((opt = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1)
+ while ((opt = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:W:-:")) != -1)
{
switch (opt)
{
- case 'A':
- SetConfigOption("debug_assertions", optarg, PGC_POSTMASTER, PGC_S_ARGV);
- break;
-
case 'B':
SetConfigOption("shared_buffers", optarg, PGC_POSTMASTER, PGC_S_ARGV);
break;
bool *foundPtr);
static void FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln);
static void AtProcExit_Buffers(int code, Datum arg);
+static void CheckForBufferLeaks(void);
static int rnode_comparator(const void *p1, const void *p2);
return result | BUF_WRITTEN;
}
-
/*
* AtEOXact_Buffers - clean up at end of transaction.
- *
- * As of PostgreSQL 8.0, buffer pins should get released by the
- * ResourceOwner mechanism. This routine is just a debugging
- * cross-check that no pins remain.
*/
void
AtEOXact_Buffers(bool isCommit)
{
-#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
- {
- int RefCountErrors = 0;
- Buffer b;
-
- for (b = 1; b <= NBuffers; b++)
- {
- if (PrivateRefCount[b - 1] != 0)
- {
- PrintBufferLeakWarning(b);
- RefCountErrors++;
- }
- }
- Assert(RefCountErrors == 0);
- }
-#endif
+ CheckForBufferLeaks();
AtEOXact_LocalBuffers(isCommit);
}
AbortBufferIO();
UnlockBuffers();
+ CheckForBufferLeaks();
+
+ /* localbuf.c needs a chance too */
+ AtProcExit_LocalBuffers();
+}
+
+/*
+ * CheckForBufferLeaks - ensure this backend holds no buffer pins
+ *
+ * As of PostgreSQL 8.0, buffer pins should get released by the
+ * ResourceOwner mechanism. This routine is just a debugging
+ * cross-check that no pins remain.
+ */
+static void
+CheckForBufferLeaks(void)
+{
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
- {
- int RefCountErrors = 0;
- Buffer b;
+ int RefCountErrors = 0;
+ Buffer b;
- for (b = 1; b <= NBuffers; b++)
+ for (b = 1; b <= NBuffers; b++)
+ {
+ if (PrivateRefCount[b - 1] != 0)
{
- if (PrivateRefCount[b - 1] != 0)
- {
- PrintBufferLeakWarning(b);
- RefCountErrors++;
- }
+ PrintBufferLeakWarning(b);
+ RefCountErrors++;
}
- Assert(RefCountErrors == 0);
}
+ Assert(RefCountErrors == 0);
#endif
-
- /* localbuf.c needs a chance too */
- AtProcExit_LocalBuffers();
}
/*
}
/*
- * AtEOXact_LocalBuffers - clean up at end of transaction.
+ * CheckForLocalBufferLeaks - ensure this backend holds no local buffer pins
*
- * This is just like AtEOXact_Buffers, but for local buffers.
+ * This is just like CheckBufferLeaks(), but for local buffers.
*/
-void
-AtEOXact_LocalBuffers(bool isCommit)
+static void
+CheckForLocalBufferLeaks(void)
{
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled && LocalRefCount)
+ if (LocalRefCount)
{
int RefCountErrors = 0;
int i;
#endif
}
+/*
+ * AtEOXact_LocalBuffers - clean up at end of transaction.
+ *
+ * This is just like AtEOXact_Buffers, but for local buffers.
+ */
+void
+AtEOXact_LocalBuffers(bool isCommit)
+{
+ CheckForLocalBufferLeaks();
+}
+
/*
* AtProcExit_LocalBuffers - ensure we have dropped pins during backend exit.
*
- * This is just like AtProcExit_Buffers, but for local buffers. We shouldn't
- * be holding any remaining pins; if we are, and assertions aren't enabled,
- * we'll fail later in DropRelFileNodeBuffers while trying to drop the temp
- * rels.
+ * This is just like AtProcExit_Buffers, but for local buffers.
*/
void
AtProcExit_LocalBuffers(void)
{
-#ifdef USE_ASSERT_CHECKING
- if (assert_enabled && LocalRefCount)
- {
- int RefCountErrors = 0;
- int i;
-
- for (i = 0; i < NLocBuffer; i++)
- {
- if (LocalRefCount[i] != 0)
- {
- Buffer b = -i - 1;
-
- PrintBufferLeakWarning(b);
- RefCountErrors++;
- }
- }
- Assert(RefCountErrors == 0);
- }
-#endif
+ /*
+ * We shouldn't be holding any remaining pins; if we are, and assertions
+ * aren't enabled, we'll fail later in DropRelFileNodeBuffers while trying
+ * to drop the temp rels.
+ */
+ CheckForLocalBufferLeaks();
}
MyProc->waitLock = NULL;
MyProc->waitProcLock = NULL;
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
{
int i;
MyProc->waitLock = NULL;
MyProc->waitProcLock = NULL;
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
{
int i;
SyncRepCleanupAtProcExit();
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
{
int i;
* postmaster/postmaster.c (the option sets should not conflict) and with
* the common help() function in main/main.c.
*/
- while ((flag = getopt(argc, argv, "A:B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1)
+ while ((flag = getopt(argc, argv, "B:bc:C:D:d:EeFf:h:ijk:lN:nOo:Pp:r:S:sTt:v:W:-:")) != -1)
{
switch (flag)
{
- case 'A':
- SetConfigOption("debug_assertions", optarg, ctx, gucsource);
- break;
-
case 'B':
SetConfigOption("shared_buffers", optarg, ctx, gucsource);
break;
AtEOXact_CatCache(bool isCommit)
{
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
+ slist_iter cache_iter;
+
+ slist_foreach(cache_iter, &CacheHdr->ch_caches)
{
- slist_iter cache_iter;
+ CatCache *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
+ dlist_iter iter;
+ int i;
- slist_foreach(cache_iter, &CacheHdr->ch_caches)
+ /* Check CatCLists */
+ dlist_foreach(iter, &ccp->cc_lists)
{
- CatCache *ccp = slist_container(CatCache, cc_next, cache_iter.cur);
- dlist_iter iter;
- int i;
+ CatCList *cl;
- /* Check CatCLists */
- dlist_foreach(iter, &ccp->cc_lists)
- {
- CatCList *cl;
+ cl = dlist_container(CatCList, cache_elem, iter.cur);
+ Assert(cl->cl_magic == CL_MAGIC);
+ Assert(cl->refcount == 0);
+ Assert(!cl->dead);
+ }
- cl = dlist_container(CatCList, cache_elem, iter.cur);
- Assert(cl->cl_magic == CL_MAGIC);
- Assert(cl->refcount == 0);
- Assert(!cl->dead);
- }
+ /* Check individual tuples */
+ for (i = 0; i < ccp->cc_nbuckets; i++)
+ {
+ dlist_head *bucket = &ccp->cc_bucket[i];
- /* Check individual tuples */
- for (i = 0; i < ccp->cc_nbuckets; i++)
+ dlist_foreach(iter, bucket)
{
- dlist_head *bucket = &ccp->cc_bucket[i];
-
- dlist_foreach(iter, bucket)
- {
- CatCTup *ct;
+ CatCTup *ct;
- ct = dlist_container(CatCTup, cache_elem, iter.cur);
- Assert(ct->ct_magic == CT_MAGIC);
- Assert(ct->refcount == 0);
- Assert(!ct->dead);
- }
+ ct = dlist_container(CatCTup, cache_elem, iter.cur);
+ Assert(ct->ct_magic == CT_MAGIC);
+ Assert(ct->refcount == 0);
+ Assert(!ct->dead);
}
}
}
found = true;
#ifdef USE_ASSERT_CHECKING
- if (assert_enabled)
{
bool isnull;
Oid check;
static void assign_session_replication_role(int newval, void *extra);
static bool check_temp_buffers(int *newval, void **extra, GucSource source);
static bool check_phony_autocommit(bool *newval, void **extra, GucSource source);
-static bool check_debug_assertions(bool *newval, void **extra, GucSource source);
static bool check_bonjour(bool *newval, void **extra, GucSource source);
static bool check_ssl(bool *newval, void **extra, GucSource source);
static bool check_stage_log_stats(bool *newval, void **extra, GucSource source);
/*
* GUC option variables that are exported from this module
*/
-#ifdef USE_ASSERT_CHECKING
-bool assert_enabled = true;
-#else
-bool assert_enabled = false;
-#endif
bool log_duration = false;
bool Debug_print_plan = false;
bool Debug_print_parse = false;
static int wal_segment_size;
static bool integer_datetimes;
static int effective_io_concurrency;
+static bool assert_enabled;
/* should be static, but commands/variable.c needs to get at this */
char *role_string;
NULL, NULL, NULL
},
{
- {"debug_assertions", PGC_USERSET, DEVELOPER_OPTIONS,
- gettext_noop("Turns on various assertion checks."),
- gettext_noop("This is a debugging aid."),
- GUC_NOT_IN_SAMPLE
+ {"debug_assertions", PGC_INTERNAL, PRESET_OPTIONS,
+ gettext_noop("Shows whether the running server has assertion checks enabled."),
+ NULL,
+ GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE
},
&assert_enabled,
#ifdef USE_ASSERT_CHECKING
#else
false,
#endif
- check_debug_assertions, NULL, NULL
+ NULL, NULL, NULL
},
{
return true;
}
-static bool
-check_debug_assertions(bool *newval, void **extra, GucSource source)
-{
-#ifndef USE_ASSERT_CHECKING
- if (*newval)
- {
- GUC_check_errmsg("assertion checking is not supported by this build");
- return false;
- }
-#endif
- return true;
-}
-
static bool
check_bonjour(bool *newval, void **extra, GucSource source)
{
*/
#define Trap(condition, errorType) \
do { \
- if ((assert_enabled) && (condition)) \
+ if (condition) \
ExceptionalCondition(CppAsString(condition), (errorType), \
__FILE__, __LINE__); \
} while (0)
* Isn't CPP fun?
*/
#define TrapMacro(condition, errorType) \
- ((bool) ((! assert_enabled) || ! (condition) || \
+ ((bool) (! (condition) || \
(ExceptionalCondition(CppAsString(condition), (errorType), \
__FILE__, __LINE__), 0)))
*/
/*
- * These declarations supports the assertion-related macros in c.h.
- * assert_enabled is here because that file doesn't have PGDLLIMPORT in the
- * right place, and ExceptionalCondition must be present, for the backend only,
- * even when assertions are not enabled.
+ * Backend only infrastructure for the the assertion-related macros in c.h.
+ *
+ * ExceptionalCondition must be present even when assertions are not enabled.
*/
-extern PGDLLIMPORT bool assert_enabled;
-
extern void ExceptionalCondition(const char *conditionName,
const char *errorType,
const char *fileName, int lineNumber) __attribute__((noreturn));