From c0921076b3a8c0a05a7c9daea3975e455ac0e515 Mon Sep 17 00:00:00 2001
From: Ayush Tiwari <ayushtiwari.slg01@gmail.com>
Date: Fri, 2 Oct 2026 09:06:30 +0000
Subject: [PATCH v3 1/2] Allow selected PANIC errors to skip core dumps

PANIC always calls abort(), which is useful for server bugs but can
worsen disk pressure for operational failures such as ENOSPC.

Add errabort(bool) to control the current report's core-dump preference,
leaving the default unchanged.  Keep errnocoredump_on_errno() as a
saved-errno convenience wrapper that suppresses only on a match.  An
explicit errabort(true) can restore abort() after suppression.

Marked PANICs use _exit(2) without cleanup callbacks, preserving existing
postmaster crash handling.  A core-worthy outer PANIC still takes
precedence over nested suppression.

Add a developer override and injection-point TAP coverage for promoted,
copied and nested errors, errno matching, explicit reversal, and the
override.  Document the reporting helpers and use worker I/O for repeated
crash-recovery cycles.

Discussion: https://postgr.es/m/20231118222911.trznxgya4hvzapva@awork3.anarazel.de
---
 doc/src/sgml/config.sgml                      |  23 ++
 doc/src/sgml/sources.sgml                     |  25 +++
 src/backend/utils/error/elog.c                |  54 ++++-
 src/backend/utils/misc/guc_parameters.dat     |   7 +
 src/include/utils/elog.h                      |   4 +
 .../injection_points--1.0.sql                 |  12 +
 .../injection_points/injection_points.c       | 208 ++++++++++++++++++
 src/test/modules/test_misc/meson.build        |   1 +
 .../modules/test_misc/t/016_panic_no_core.pl  |  82 +++++++
 9 files changed, 413 insertions(+), 3 deletions(-)
 create mode 100644 src/test/modules/test_misc/t/016_panic_no_core.pl

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index f36fbb60101..e57cc0fef61 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -13547,6 +13547,29 @@ LOG:  CleanUpLock: deleting: lock(0xb7acd844) id(24688,24696,0,0,0,1)
       </listitem>
      </varlistentry>
 
+     <varlistentry id="guc-force-core-dump-on-panic" xreflabel="force_core_dump_on_panic">
+       <term><varname>force_core_dump_on_panic</varname> (<type>boolean</type>)
+       <indexterm>
+        <primary><varname>force_core_dump_on_panic</varname> configuration parameter</primary>
+       </indexterm>
+       </term>
+       <listitem>
+        <para>
+         Some <literal>PANIC</literal> errors are marked to terminate without
+         requesting a core dump.  When this option is set to
+         <literal>on</literal>, those errors call
+         <function>abort()</function> instead, which normally produces a core
+         dump file.  This can be useful for debugging, but repeated failures
+         can consume significant disk space.  Unlike
+         <xref linkend="guc-send-abort-for-crash"/>, this parameter controls
+         the process reporting the <literal>PANIC</literal>, not the other
+         processes terminated by the postmaster afterwards.  This parameter
+         can only be set in the <filename>postgresql.conf</filename> file or on
+         the server command line.
+        </para>
+       </listitem>
+      </varlistentry>
+
      <varlistentry id="guc-debug-logical-replication-streaming" xreflabel="debug_logical_replication_streaming">
       <term><varname>debug_logical_replication_streaming</varname> (<type>enum</type>)
       <indexterm>
diff --git a/doc/src/sgml/sources.sgml b/doc/src/sgml/sources.sgml
index 760f9b69d47..3026f10ff8d 100644
--- a/doc/src/sgml/sources.sgml
+++ b/doc/src/sgml/sources.sgml
@@ -392,6 +392,31 @@ ereport(ERROR,
      too much.
     </para>
    </listitem>
+     <listitem>
+        <para>
+         <function>errabort(bool do_abort)</function> controls whether a
+         <literal>PANIC</literal> calls <function>abort()</function>, the default.
+         Passing <literal>false</literal> selects <function>_exit(2)</function>
+         instead, avoiding a core dump without running cleanup callbacks or
+         changing postmaster crash handling.  Calling
+         <function>errabort(true)</function> restores the default for the current
+         report.  This preference also applies to errors promoted to
+         <literal>PANIC</literal>, but does not change ordinary
+         <literal>ERROR</literal> or <literal>FATAL</literal> termination.
+         An outer <literal>PANIC</literal> that requests a core dump, or
+         <xref linkend="guc-force-core-dump-on-panic"/>, still overrides suppression.
+        </para>
+     </listitem>
+     <listitem>
+        <para>
+         <function>errnocoredump_on_errno(int errnum)</function> is a convenience
+         wrapper that calls <function>errabort(false)</function> when the
+         <literal>errno</literal> saved at the start of the error report matches
+         <parameter>errnum</parameter>.  A nonmatch leaves the preference unchanged,
+         so multiple calls can select more than one error number without undoing
+         an earlier match.
+        </para>
+     </listitem>
   </itemizedlist>
    </para>
 
diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c
index b9d2c96b97a..4d588823719 100644
--- a/src/backend/utils/error/elog.c
+++ b/src/backend/utils/error/elog.c
@@ -117,6 +117,7 @@ int			Log_destination = LOG_DESTINATION_STDERR;
 char	   *Log_destination_string = NULL;
 bool		syslog_sequence_numbers = true;
 bool		syslog_split_messages = true;
+bool		force_core_dump_on_panic = false;
 
 /* Processed form of backtrace_functions GUC */
 static char *backtrace_function_list;
@@ -487,6 +488,7 @@ errfinish(const char *filename, int lineno, const char *funcname)
 {
 	ErrorData  *edata = &errordata[errordata_stack_depth];
 	int			elevel;
+	bool		no_core_dump;
 	MemoryContext oldcontext;
 	ErrorContextCallback *econtext;
 
@@ -521,6 +523,17 @@ errfinish(const char *filename, int lineno, const char *funcname)
 		 econtext = econtext->previous)
 		econtext->callback(econtext->arg);
 
+	/*
+	 * Capture this before releasing the current error stack entry below.  A
+	 * core-worthy outer PANIC must not be downgraded by a nested error.
+	 */
+	no_core_dump = edata->no_core_dump;
+	for (int i = 0; no_core_dump && i < errordata_stack_depth; i++)
+	{
+		if (errordata[i].elevel >= PANIC && !errordata[i].no_core_dump)
+			no_core_dump = false;
+	}
+
 	/*
 	 * If ERROR (not more nor less) we pass it off to the current handler.
 	 * Printing it and popping the stack is the responsibility of the handler.
@@ -611,13 +624,16 @@ errfinish(const char *filename, int lineno, const char *funcname)
 	if (elevel >= PANIC)
 	{
 		/*
-		 * Serious crash time. Postmaster will observe SIGABRT process exit
-		 * status and kill the other backends too.
+		 * Serious crash time.  SIGABRT and exit code 2 both trigger
+		 * postmaster crash handling.  Marked errors use _exit(2) to avoid
+		 * core dumps without running cleanup callbacks.
 		 *
-		 * XXX: what if we are *in* the postmaster?  abort() won't kill our
+		 * XXX: what if we are *in* the postmaster?  Neither path kills our
 		 * children...
 		 */
 		fflush(NULL);
+		if (no_core_dump && !force_core_dump_on_panic)
+			_exit(2);
 		abort();
 	}
 
@@ -1652,6 +1668,37 @@ errhidecontext(bool hide_ctx)
 	return 0;					/* return value does not matter */
 }
 
+/*
+ * errabort --- set whether a PANIC should call abort()
+ */
+int
+errabort(bool do_abort)
+{
+	ErrorData  *edata = &errordata[errordata_stack_depth];
+
+	CHECK_STACK_DEPTH();
+	edata->no_core_dump = !do_abort;
+
+	return 0;
+}
+
+/*
+ * errnocoredump_on_errno --- skip a core dump for the specified errno
+ */
+int
+errnocoredump_on_errno(int errnum)
+{
+	ErrorData  *edata = &errordata[errordata_stack_depth];
+
+	/* we don't bother incrementing recursion_depth */
+	CHECK_STACK_DEPTH();
+
+	if (edata->saved_errno == errnum)
+		return errabort(false);
+
+	return 0;					/* return value does not matter */
+}
+
 /*
  * errposition --- add cursor position to the current error
  */
@@ -2130,6 +2177,7 @@ ThrowErrorData(ErrorData *edata)
 	newedata->internalpos = edata->internalpos;
 	if (edata->internalquery)
 		newedata->internalquery = pstrdup(edata->internalquery);
+	newedata->no_core_dump = edata->no_core_dump;
 
 	MemoryContextSwitchTo(oldcontext);
 	recursion_depth--;
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index c57441f7d98..88b88160265 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -1104,6 +1104,13 @@
   options => 'file_extend_method_options',
 },
 
+{ name => 'force_core_dump_on_panic', type => 'bool', context => 'PGC_SIGHUP', group => 'DEVELOPER_OPTIONS',
+  short_desc => 'Force core dumps for PANIC errors marked to skip them.',
+  flags => 'GUC_NOT_IN_SAMPLE',
+  variable => 'force_core_dump_on_panic',
+  boot_val => 'false',
+},
+
 { name => 'from_collapse_limit', type => 'int', context => 'PGC_USERSET', group => 'QUERY_TUNING_OTHER',
   short_desc => 'Sets the FROM-list size beyond which subqueries are not collapsed.',
   long_desc => 'The planner will merge subqueries into upper queries if the resulting FROM list would have no more than this many items.',
diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h
index 6ae376ba001..6446e5d250f 100644
--- a/src/include/utils/elog.h
+++ b/src/include/utils/elog.h
@@ -219,6 +219,8 @@ extern int	errcontext_msg(const char *fmt, ...) pg_attribute_printf(1, 2);
 
 extern int	errhidestmt(bool hide_stmt);
 extern int	errhidecontext(bool hide_ctx);
+extern int	errabort(bool do_abort);
+extern int	errnocoredump_on_errno(int errnum);
 
 extern int	errbacktrace(void);
 
@@ -422,6 +424,7 @@ extern PGDLLIMPORT ErrorContextCallback *error_context_stack;
 	pg_re_throw()
 
 extern PGDLLIMPORT sigjmp_buf *PG_exception_stack;
+extern PGDLLIMPORT bool force_core_dump_on_panic;
 
 
 /* Stuff that error handlers might want to use */
@@ -439,6 +442,7 @@ typedef struct ErrorData
 	bool		output_to_client;	/* will report to client? */
 	bool		hide_stmt;		/* true to prevent STATEMENT: inclusion */
 	bool		hide_ctx;		/* true to prevent CONTEXT: inclusion */
+	bool		no_core_dump;	/* true to skip core dump for PANIC */
 	const char *filename;		/* __FILE__ of ereport() call */
 	int			lineno;			/* __LINE__ of ereport() call */
 	const char *funcname;		/* __func__ of ereport() call */
diff --git a/src/test/modules/injection_points/injection_points--1.0.sql b/src/test/modules/injection_points/injection_points--1.0.sql
index 2efb307f5bf..bf21d94ecf6 100644
--- a/src/test/modules/injection_points/injection_points--1.0.sql
+++ b/src/test/modules/injection_points/injection_points--1.0.sql
@@ -48,6 +48,18 @@ RETURNS void
 AS 'MODULE_PATHNAME', 'injection_points_run'
 LANGUAGE C PARALLEL UNSAFE;
 
+-- Execute an injection point from a critical section.
+CREATE FUNCTION injection_points_run_in_critical_section(IN point_name TEXT)
+RETURNS void
+AS 'MODULE_PATHNAME', 'injection_points_run_in_critical_section'
+LANGUAGE C STRICT PARALLEL UNSAFE;
+
+-- Replace SIGABRT with a distinctive process exit for tests.
+CREATE FUNCTION injection_points_intercept_abort()
+RETURNS void
+AS 'MODULE_PATHNAME', 'injection_points_intercept_abort'
+LANGUAGE C STRICT PARALLEL UNSAFE;
+
 --
 -- injection_points_cached()
 --
diff --git a/src/test/modules/injection_points/injection_points.c b/src/test/modules/injection_points/injection_points.c
index 5e1bbc2f5c9..a1a5ec13f9b 100644
--- a/src/test/modules/injection_points/injection_points.c
+++ b/src/test/modules/injection_points/injection_points.c
@@ -17,6 +17,11 @@
 
 #include "postgres.h"
 
+#include <signal.h>
+#ifndef WIN32
+#include <unistd.h>
+#endif
+
 #include "fmgr.h"
 #include "funcapi.h"
 #include "injection_points.h"
@@ -75,6 +80,24 @@ static InjectionPointSharedState *inj_state = NULL;
 extern PGDLLEXPORT void injection_error(const char *name,
 										const void *private_data,
 										void *arg);
+extern PGDLLEXPORT void injection_error_disk_full(const char *name,
+												  const void *private_data,
+												  void *arg);
+extern PGDLLEXPORT void injection_error_io(const char *name,
+										   const void *private_data,
+										   void *arg);
+extern PGDLLEXPORT void injection_error_disk_full_rethrow_panic(const char *name,
+																const void *private_data,
+																void *arg);
+extern PGDLLEXPORT void injection_panic_disk_full(const char *name,
+												  const void *private_data,
+												  void *arg);
+extern PGDLLEXPORT void injection_panic_core_reenabled(const char *name,
+													   const void *private_data,
+													   void *arg);
+extern PGDLLEXPORT void injection_panic_with_nested_disk_full(const char *name,
+															  const void *private_data,
+															  void *arg);
 extern PGDLLEXPORT void injection_notice(const char *name,
 										 const void *private_data,
 										 void *arg);
@@ -87,12 +110,41 @@ static bool injection_point_local = false;
 
 static void injection_shmem_request(void *arg);
 static void injection_shmem_init(void *arg);
+#ifdef WIN32
+static void injection_abort_handler(int signal);
+#else
+static void injection_abort_handler(SIGNAL_ARGS);
+#endif
+static void injection_nested_disk_full_panic(void *arg);
 
 static const ShmemCallbacks injection_shmem_callbacks = {
 	.request_fn = injection_shmem_request,
 	.init_fn = injection_shmem_init,
 };
 
+static void
+#ifdef WIN32
+injection_abort_handler(int signal)
+#else
+injection_abort_handler(SIGNAL_ARGS)
+#endif
+{
+	_exit(42);
+}
+
+static void
+injection_nested_disk_full_panic(void *arg)
+{
+	ErrorContextCallback *callback = arg;
+
+	error_context_stack = callback->previous;
+	errno = ENOSPC;
+	ereport(PANIC,
+			(errcode_for_file_access(),
+			 errnocoredump_on_errno(ENOSPC),
+			 errmsg("nested disk-full PANIC")));
+}
+
 /*
  * Routine for shared memory area initialization, used as a callback
  * when initializing dynamically with a DSM or when loading the module.
@@ -206,6 +258,120 @@ injection_error(const char *name, const void *private_data, void *arg)
 		elog(ERROR, "error triggered for injection point %s", name);
 }
 
+void
+injection_error_disk_full(const char *name, const void *private_data, void *arg)
+{
+	const InjectionPointCondition *condition = private_data;
+
+	if (!injection_point_allowed(condition, arg))
+		return;
+
+	errno = ENOSPC;
+	/* A later nonmatch must not undo suppression. */
+	ereport(ERROR,
+			(errcode_for_file_access(),
+			 errnocoredump_on_errno(ENOSPC),
+			 errnocoredump_on_errno(EIO),
+			 errmsg("error triggered for injection point %s", name)));
+}
+
+void
+injection_error_io(const char *name, const void *private_data, void *arg)
+{
+	const InjectionPointCondition *condition = private_data;
+
+	if (!injection_point_allowed(condition, arg))
+		return;
+
+	errno = EIO;
+	ereport(ERROR,
+			(errcode_for_file_access(),
+			 errnocoredump_on_errno(ENOSPC),
+			 errmsg("I/O error triggered for injection point %s", name)));
+}
+
+void
+injection_error_disk_full_rethrow_panic(const char *name,
+										const void *private_data, void *arg)
+{
+	const InjectionPointCondition *condition = private_data;
+	MemoryContext oldcontext = CurrentMemoryContext;
+
+	if (!injection_point_allowed(condition, arg))
+		return;
+
+	PG_TRY();
+	{
+		errno = ENOSPC;
+		ereport(ERROR,
+				(errcode_for_file_access(),
+				 errnocoredump_on_errno(ENOSPC),
+				 errmsg("rethrow disk-full PANIC for injection point %s", name)));
+	}
+	PG_CATCH();
+	{
+		ErrorData  *edata;
+
+		MemoryContextSwitchTo(oldcontext);
+		edata = CopyErrorData();
+		FlushErrorState();
+		edata->elevel = PANIC;
+		ThrowErrorData(edata);
+	}
+	PG_END_TRY();
+}
+
+void
+injection_panic_disk_full(const char *name, const void *private_data, void *arg)
+{
+	const InjectionPointCondition *condition = private_data;
+
+	if (!injection_point_allowed(condition, arg))
+		return;
+
+	errno = ENOSPC;
+	ereport(PANIC,
+			(errcode_for_file_access(),
+			 errabort(false),
+			 errmsg("panic triggered for injection point %s", name)));
+}
+
+void
+injection_panic_core_reenabled(const char *name,
+							   const void *private_data, void *arg)
+{
+	const InjectionPointCondition *condition = private_data;
+
+	if (!injection_point_allowed(condition, arg))
+		return;
+
+	errno = ENOSPC;
+	ereport(PANIC,
+			(errcode_for_file_access(),
+			 errabort(false),
+			 errabort(true),
+			 errmsg("core dump re-enabled for injection point %s", name)));
+}
+
+void
+injection_panic_with_nested_disk_full(const char *name,
+									  const void *private_data, void *arg)
+{
+	const InjectionPointCondition *condition = private_data;
+	ErrorContextCallback callback;
+
+	if (!injection_point_allowed(condition, arg))
+		return;
+
+	callback.previous = error_context_stack;
+	callback.callback = injection_nested_disk_full_panic;
+	callback.arg = &callback;
+	error_context_stack = &callback;
+
+	ereport(PANIC,
+			(errmsg("outer core-worthy PANIC for injection point %s", name)));
+}
+
 void
 injection_notice(const char *name, const void *private_data, void *arg)
 {
@@ -336,6 +502,18 @@ injection_points_attach(PG_FUNCTION_ARGS)
 
 	if (strcmp(action, "error") == 0)
 		function = "injection_error";
+	else if (strcmp(action, "error_disk_full") == 0)
+		function = "injection_error_disk_full";
+	else if (strcmp(action, "error_io") == 0)
+		function = "injection_error_io";
+	else if (strcmp(action, "error_disk_full_rethrow_panic") == 0)
+		function = "injection_error_disk_full_rethrow_panic";
+	else if (strcmp(action, "panic_disk_full") == 0)
+		function = "injection_panic_disk_full";
+	else if (strcmp(action, "panic_core_reenabled") == 0)
+		function = "injection_panic_core_reenabled";
+	else if (strcmp(action, "panic_with_nested_disk_full") == 0)
+		function = "injection_panic_with_nested_disk_full";
 	else if (strcmp(action, "notice") == 0)
 		function = "injection_notice";
 	else if (strcmp(action, "wait") == 0)
@@ -455,6 +633,36 @@ injection_points_run(PG_FUNCTION_ARGS)
 	PG_RETURN_VOID();
 }
 
+/* Trigger an injection point from a critical section. */
+PG_FUNCTION_INFO_V1(injection_points_run_in_critical_section);
+Datum
+injection_points_run_in_critical_section(PG_FUNCTION_ARGS)
+{
+	char	   *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
+
+	INJECTION_POINT_LOAD(name);
+	START_CRIT_SECTION();
+	INJECTION_POINT_CACHED(name, NULL);
+	END_CRIT_SECTION();
+
+	PG_RETURN_VOID();
+}
+
+/* Make abort() observable without producing a core file. */
+PG_FUNCTION_INFO_V1(injection_points_intercept_abort);
+Datum
+injection_points_intercept_abort(PG_FUNCTION_ARGS)
+{
+#ifdef WIN32
+	if (signal(SIGABRT, injection_abort_handler) == SIG_ERR)
+		elog(ERROR, "could not install SIGABRT handler");
+#else
+	pqsignal(SIGABRT, injection_abort_handler);
+#endif
+
+	PG_RETURN_VOID();
+}
+
 /*
  * SQL function for triggering an injection point from cache.
  */
diff --git a/src/test/modules/test_misc/meson.build b/src/test/modules/test_misc/meson.build
index 5d81f5b13be..4c520a339f8 100644
--- a/src/test/modules/test_misc/meson.build
+++ b/src/test/modules/test_misc/meson.build
@@ -24,6 +24,7 @@ tests += {
       't/013_temp_obj_multisession.pl',
       't/014_log_statement_max_length.pl',
       't/015_temp_schema_exit_deferrable.pl',
+      't/016_panic_no_core.pl',
     ],
     # The injection points are cluster-wide, so disable installcheck
     'runningcheck': false,
diff --git a/src/test/modules/test_misc/t/016_panic_no_core.pl b/src/test/modules/test_misc/t/016_panic_no_core.pl
new file mode 100644
index 00000000000..d0fd259856a
--- /dev/null
+++ b/src/test/modules/test_misc/t/016_panic_no_core.pl
@@ -0,0 +1,82 @@
+# Copyright (c) 2026, PostgreSQL Global Development Group
+
+use strict;
+use warnings FATAL => 'all';
+use PostgreSQL::Test::Cluster;
+use PostgreSQL::Test::Utils;
+use Test::More;
+
+plan skip_all => 'Injection points not supported by this build'
+  unless $ENV{enable_injection_points} eq 'yes';
+
+my $node = PostgreSQL::Test::Cluster->new('panic_no_core');
+$node->init;
+# Avoid exhausting io_uring resources across repeated crash recovery.
+$node->append_conf(
+	'postgresql.conf', qq{
+restart_after_crash = on
+log_min_messages = warning
+io_method = worker
+});
+$node->start;
+
+is($node->safe_psql('postgres', 'SHOW force_core_dump_on_panic'),
+	'off', 'core dump override defaults to off');
+
+$node->safe_psql('postgres', 'CREATE EXTENSION injection_points');
+
+sub check_panic
+{
+	my ($name, $action, $critical, $exit_code, $message) = @_;
+
+	$node->safe_psql('postgres',
+		"SELECT injection_points_attach('$name', '$action')");
+	my $log_offset = -s $node->logfile;
+	my $run_function =
+	  $critical
+	  ? 'injection_points_run_in_critical_section'
+	  : 'injection_points_run';
+	my ($ret) = $node->psql(
+		'postgres', qq{
+SET log_min_messages = panic;
+SELECT injection_points_intercept_abort();
+SELECT $run_function('$name');
+});
+
+	isnt($ret, 0, "$name terminates the backend");
+	$node->wait_for_log(qr/PANIC:.*\Q$message\E/, $log_offset);
+	$node->wait_for_log(qr/\(PID \d+\) exited with exit code $exit_code/,
+		$log_offset);
+	ok($node->poll_query_until('postgres', undef, ''),
+		"server recovers from $name");
+}
+
+check_panic('panic-no-core-promoted', 'error_disk_full', 1, 2,
+	'error triggered for injection point panic-no-core-promoted');
+check_panic('panic-no-core-explicit', 'panic_disk_full', 0, 2,
+	'panic triggered for injection point panic-no-core-explicit');
+check_panic('panic-no-core-rethrow', 'error_disk_full_rethrow_panic',
+	0, 2,
+	'rethrow disk-full PANIC for injection point panic-no-core-rethrow');
+check_panic('panic-core-io', 'error_io', 1, 42,
+	'I/O error triggered for injection point panic-core-io');
+check_panic('panic-core-nested', 'panic_with_nested_disk_full', 0, 42,
+	'nested disk-full PANIC');
+check_panic('panic-core-promoted', 'error', 1, 42,
+	'error triggered for injection point panic-core-promoted');
+check_panic('panic-core-reenabled', 'panic_core_reenabled', 0, 42,
+	'core dump re-enabled for injection point panic-core-reenabled');
+
+$node->safe_psql('postgres',
+	'ALTER SYSTEM SET force_core_dump_on_panic = on');
+$node->safe_psql('postgres', 'SELECT pg_reload_conf()');
+ok( $node->poll_query_until(
+		'postgres',
+		q{SELECT current_setting('force_core_dump_on_panic') = 'on'}),
+	'core dump override is active');
+
+check_panic('panic-core-override', 'panic_disk_full', 0, 42,
+	'panic triggered for injection point panic-core-override');
+
+$node->stop;
+done_testing();

base-commit: 80931d131a95ddcddc7b671d4fee7aceeb12a314
-- 
2.43.0

