* mode; "curl up and die" is a sufficient response for all these cases.
* Let's set that handling explicitly, as documentation if nothing else.
*/
- pqsignal(SIGHUP, SIG_DFL);
- pqsignal(SIGINT, SIG_DFL);
- pqsignal(SIGTERM, SIG_DFL);
- pqsignal(SIGQUIT, SIG_DFL);
+ pqsignal(SIGHUP, PG_SIG_DFL);
+ pqsignal(SIGINT, PG_SIG_DFL);
+ pqsignal(SIGTERM, PG_SIG_DFL);
+ pqsignal(SIGQUIT, PG_SIG_DFL);
}
/* ----------------------------------------------------------------
pg_signal_array[i].sa_handler = SIG_DFL;
pg_signal_array[i].sa_mask = 0;
pg_signal_array[i].sa_flags = 0;
- pg_signal_defaults[i] = SIG_IGN;
+ pg_signal_defaults[i] = PG_SIG_IGN;
}
pg_signal_mask = 0;
pg_signal_queue = 0;
{
/* Execute this signal */
struct sigaction *act = &pg_signal_array[i];
- pqsigfunc sig = act->sa_handler;
+ pqsigfunc sig = (pqsigfunc) (pg_funcptr_t) act->sa_handler;
- if (sig == SIG_DFL)
+ if (sig == PG_SIG_DFL)
sig = pg_signal_defaults[i];
pg_signal_queue &= ~sigmask(i);
- if (sig != SIG_ERR && sig != SIG_IGN && sig != SIG_DFL)
+ if (sig != (pqsigfunc) (pg_funcptr_t) SIG_ERR && sig != PG_SIG_IGN && sig != PG_SIG_DFL)
{
sigset_t block_mask;
sigset_t save_mask;
+ struct pg_signal_info nodata;
+
+ nodata.pid = 0;
+ nodata.uid = 0;
LeaveCriticalSection(&pg_signal_crit_sec);
block_mask |= sigmask(i);
sigprocmask(SIG_BLOCK, &block_mask, &save_mask);
- sig(i);
+ sig(i, &nodata);
sigprocmask(SIG_SETMASK, &save_mask, NULL);
EnterCriticalSection(&pg_signal_crit_sec);
InitializeTimeouts(); /* establishes SIGALRM handler */
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, avl_sigusr2_handler);
pqsignal(SIGFPE, FloatExceptionHandler);
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* Create a per-backend PGPROC struct in shared memory. We must do this
InitializeTimeouts(); /* establishes SIGALRM handler */
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
pqsignal(SIGFPE, FloatExceptionHandler);
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* Create a per-backend PGPROC struct in shared memory. We must do this
}
else
{
- pqsignal(SIGINT, SIG_IGN);
- pqsignal(SIGUSR1, SIG_IGN);
- pqsignal(SIGFPE, SIG_IGN);
+ pqsignal(SIGINT, PG_SIG_IGN);
+ pqsignal(SIGUSR1, PG_SIG_IGN);
+ pqsignal(SIGFPE, PG_SIG_IGN);
}
pqsignal(SIGTERM, die);
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGHUP, SIG_IGN);
+ pqsignal(SIGHUP, PG_SIG_IGN);
InitializeTimeouts(); /* establishes SIGALRM handler */
- pqsignal(SIGPIPE, SIG_IGN);
- pqsignal(SIGUSR2, SIG_IGN);
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* If an exception is encountered, processing resumes here.
* Properly accept or ignore signals that might be sent to us.
*/
pqsignal(SIGHUP, SignalHandlerForConfigReload);
- pqsignal(SIGINT, SIG_IGN);
+ pqsignal(SIGINT, PG_SIG_IGN);
pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
/*
* Reset some signals that are accepted by postmaster but not here
*/
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* We just started, assume there has been either a shutdown or
*/
pqsignal(SIGHUP, SignalHandlerForConfigReload);
pqsignal(SIGINT, ReqShutdownXLOG);
- pqsignal(SIGTERM, SIG_IGN); /* ignore SIGTERM */
+ pqsignal(SIGTERM, PG_SIG_IGN); /* ignore SIGTERM */
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SignalHandlerForShutdownRequest);
/*
* Reset some signals that are accepted by postmaster but not here
*/
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* Initialize so that first time-driven event happens at the correct time.
pqsignal(SIGTERM, die);
pqsignal(SIGINT, launcher_cancel_handler);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
BackgroundWorkerUnblockSignals();
* except for SIGHUP, SIGTERM, SIGUSR1, SIGUSR2, and SIGQUIT.
*/
pqsignal(SIGHUP, SignalHandlerForConfigReload);
- pqsignal(SIGINT, SIG_IGN);
+ pqsignal(SIGINT, PG_SIG_IGN);
pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, pgarch_waken_stop);
/* Reset some signals that are accepted by postmaster but not here */
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/* Unblock signals (they were blocked when the postmaster forked us) */
sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
pqsignal(SIGINT, handle_pm_shutdown_request_signal);
pqsignal(SIGQUIT, handle_pm_shutdown_request_signal);
pqsignal(SIGTERM, handle_pm_shutdown_request_signal);
- pqsignal(SIGALRM, SIG_IGN); /* ignored */
- pqsignal(SIGPIPE, SIG_IGN); /* ignored */
+ pqsignal(SIGALRM, PG_SIG_IGN); /* ignored */
+ pqsignal(SIGPIPE, PG_SIG_IGN); /* ignored */
pqsignal(SIGUSR1, handle_pm_pmsignal_signal);
pqsignal(SIGUSR2, dummy_handler); /* unused, reserve for children */
pqsignal(SIGCHLD, handle_pm_child_exit_signal);
* child processes should just allow the inherited settings to stand.
*/
#ifdef SIGTTIN
- pqsignal(SIGTTIN, SIG_IGN); /* ignored */
+ pqsignal(SIGTTIN, PG_SIG_IGN); /* ignored */
#endif
#ifdef SIGTTOU
- pqsignal(SIGTTOU, SIG_IGN); /* ignored */
+ pqsignal(SIGTTOU, PG_SIG_IGN); /* ignored */
#endif
/* ignore SIGXFSZ, so that ulimit violations work like disk full */
#ifdef SIGXFSZ
- pqsignal(SIGXFSZ, SIG_IGN); /* ignored */
+ pqsignal(SIGXFSZ, PG_SIG_IGN); /* ignored */
#endif
/* Begin accepting signals. */
* Dummy signal handler
*
* We use this for signals that we don't actually use in the postmaster,
- * but we do use in backends. If we were to SIG_IGN such signals in the
+ * but we do use in backends. If we were to PG_SIG_IGN such signals in the
* postmaster, then a newly started backend might drop a signal that arrives
* before it's able to reconfigure its signal processing. (See notes in
* tcop/postgres.c.)
* Properly accept or ignore signals the postmaster might send us.
*/
pqsignal(SIGHUP, StartupProcSigHupHandler); /* reload config file */
- pqsignal(SIGINT, SIG_IGN); /* ignore query cancel */
+ pqsignal(SIGINT, PG_SIG_IGN); /* ignore query cancel */
pqsignal(SIGTERM, StartupProcShutdownHandler); /* request shutdown */
/* SIGQUIT handler was already set up by InitPostmasterChild */
InitializeTimeouts(); /* establishes SIGALRM handler */
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, StartupProcTriggerHandler);
/*
* Reset some signals that are accepted by postmaster but not here
*/
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* Register timeouts needed for standby mode
pqsignal(SIGHUP, SignalHandlerForConfigReload); /* set flag to read config
* file */
- pqsignal(SIGINT, SIG_IGN);
- pqsignal(SIGTERM, SIG_IGN);
- pqsignal(SIGQUIT, SIG_IGN);
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGINT, PG_SIG_IGN);
+ pqsignal(SIGTERM, PG_SIG_IGN);
+ pqsignal(SIGQUIT, PG_SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, sigUsr1Handler); /* request log rotation */
- pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
/*
* Reset some signals that are accepted by postmaster but not here
*/
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
sigprocmask(SIG_SETMASK, &UnBlockSig, NULL);
* Properly accept or ignore signals the postmaster might send us
*/
pqsignal(SIGHUP, SignalHandlerForConfigReload);
- pqsignal(SIGINT, SIG_IGN); /* no query to cancel */
+ pqsignal(SIGINT, PG_SIG_IGN); /* no query to cancel */
pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN); /* not used */
+ pqsignal(SIGUSR2, PG_SIG_IGN); /* not used */
/* Advertise ourselves. */
on_shmem_exit(WalSummarizerShutdown, (Datum) 0);
/*
* Reset some signals that are accepted by postmaster but not here
*/
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* If an exception is encountered, processing resumes here.
* Properly accept or ignore signals the postmaster might send us
*/
pqsignal(SIGHUP, SignalHandlerForConfigReload);
- pqsignal(SIGINT, SIG_IGN); /* no query to cancel */
+ pqsignal(SIGINT, PG_SIG_IGN); /* no query to cancel */
pqsignal(SIGTERM, SignalHandlerForShutdownRequest);
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN); /* not used */
+ pqsignal(SIGUSR2, PG_SIG_IGN); /* not used */
/*
* Reset some signals that are accepted by postmaster but not here
*/
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/*
* Create a memory context that we will do all our work in. We do this so
pqsignal(SIGTERM, die);
pqsignal(SIGFPE, FloatExceptionHandler);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
check_and_set_sync_info(MyProcPid);
*/
if (ProcDiePending)
{
- /*
- * ProcDieSenderPid/Uid are read directly from the globals here
- * rather than copied to locals first; a second SIGTERM could
- * change them between reads, but that is harmless because the
- * process is about to die anyway. The signal sender detail is
- * inlined rather than using a separate errdetail() call because
- * it must be appended to the existing detail message.
- */
- ereport(WARNING,
- (errcode(ERRCODE_ADMIN_SHUTDOWN),
- errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"),
- errdetail("The transaction has already committed locally, but might not have been replicated to the standby.%s",
- ProcDieSenderPid == 0 ? "" :
- psprintf("\nSignal sent by PID %d, UID %d.",
- (int) ProcDieSenderPid,
- (int) ProcDieSenderUid))));
+ if (ProcDieSenderPid != 0)
+ ereport(WARNING,
+ (errcode(ERRCODE_ADMIN_SHUTDOWN),
+ errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"),
+ errdetail("The transaction has already committed locally, but might not have been replicated to the standby. Signal sent by PID %d, UID %d.",
+ (int) ProcDieSenderPid,
+ (int) ProcDieSenderUid)));
+ else
+ ereport(WARNING,
+ (errcode(ERRCODE_ADMIN_SHUTDOWN),
+ errmsg("canceling the wait for synchronous replication and terminating connection due to administrator command"),
+ errdetail("The transaction has already committed locally, but might not have been replicated to the standby.")));
whereToSendOutput = DestNone;
SyncRepCancelWait();
break;
/* Properly accept or ignore signals the postmaster might send us */
pqsignal(SIGHUP, SignalHandlerForConfigReload); /* set flag to read config
* file */
- pqsignal(SIGINT, SIG_IGN);
+ pqsignal(SIGINT, PG_SIG_IGN);
pqsignal(SIGTERM, die); /* request shutdown */
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
/* Reset some signals that are accepted by postmaster but not here */
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
/* Load the libpq-specific functions */
load_file("libpqwalreceiver", false);
pqsignal(SIGTERM, die); /* request shutdown */
/* SIGQUIT handler was already set up by InitPostmasterChild */
InitializeTimeouts(); /* establishes SIGALRM handler */
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, WalSndLastCycleHandler); /* request a last cycle and
* shutdown */
/* Reset some signals that are accepted by postmaster but not here */
- pqsignal(SIGCHLD, SIG_DFL);
+ pqsignal(SIGCHLD, PG_SIG_DFL);
}
/* Register shared-memory space needed by walsender */
* Ignore SIGTERM, will get explicit shutdown via SIGUSR2 later in the
* shutdown sequence, similar to checkpointer.
*/
- pqsignal(SIGTERM, SIG_IGN);
+ pqsignal(SIGTERM, PG_SIG_IGN);
/* SIGQUIT handler was already set up by InitPostmasterChild */
- pqsignal(SIGALRM, SIG_IGN);
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGALRM, PG_SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SignalHandlerForShutdownRequest);
TryAgain:
fflush(NULL);
- pqsignal(SIGPIPE, SIG_DFL);
+ pqsignal(SIGPIPE, PG_SIG_DFL);
errno = 0;
file = popen(command, mode);
save_errno = errno;
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
errno = save_errno;
if (file != NULL)
{
#ifdef WAIT_USE_KQUEUE
/* Ignore SIGURG, because we'll receive it via kqueue. */
- pqsignal(SIGURG, SIG_IGN);
+ pqsignal(SIGURG, PG_SIG_IGN);
#endif
}
{
InterruptPending = true;
ProcDiePending = true;
+
+ /*
+ * Record who sent the signal. Will be 0 on platforms without
+ * SA_SIGINFO, which is fine -- ProcessInterrupts() checks for that.
+ * Only set on the first SIGTERM so we report the original sender.
+ */
+ if (ProcDieSenderPid == 0)
+ {
+ ProcDieSenderPid = pg_siginfo->pid;
+ ProcDieSenderUid = pg_siginfo->uid;
+ }
}
/* for the cumulative stats system */
* returns to outer loop. This seems safer than forcing exit in the
* midst of output during who-knows-what operation...
*/
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
- pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGUSR2, PG_SIG_IGN);
pqsignal(SIGFPE, FloatExceptionHandler);
/*
* Reset some signals that are accepted by postmaster but not by
* backend
*/
- pqsignal(SIGCHLD, SIG_DFL); /* system() requires this on some
- * platforms */
+ pqsignal(SIGCHLD, PG_SIG_DFL); /* system() requires this on some
+ * platforms */
}
/* Early initialization */
pqsignal(SIGQUIT, trapsig);
/* Ignore SIGPIPE when writing to backend, so we can clean up */
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
/* Prevent SIGSYS so we can probe for kernel calls that might not work */
- pqsignal(SIGSYS, SIG_IGN);
+ pqsignal(SIGSYS, PG_SIG_IGN);
#endif
}
* Clear the signal handler, and send the signal again, to terminate the
* process as normal.
*/
- pqsignal(postgres_signal_arg, SIG_DFL);
+ pqsignal(postgres_signal_arg, PG_SIG_DFL);
raise(postgres_signal_arg);
}
* signal handler. That could muck up our attempt to send PQcancel, so
* disable the signals that set_cancel_handler enabled.
*/
- pqsignal(SIGINT, SIG_IGN);
- pqsignal(SIGTERM, SIG_IGN);
- pqsignal(SIGQUIT, SIG_IGN);
+ pqsignal(SIGINT, PG_SIG_IGN);
+ pqsignal(SIGTERM, PG_SIG_IGN);
+ pqsignal(SIGQUIT, PG_SIG_IGN);
/*
* If we're in the leader, forward signal to all workers. (It seems best
* the workers to inherit this setting, though.
*/
#ifndef WIN32
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
#endif
/*
is($ret, 2, 'server crash: psql exit code');
like($out, qr/before/, 'server crash: output before crash');
unlike($out, qr/AFTER/, 'server crash: no output after crash');
+my $detail_re = check_pg_config("#define HAVE_SA_SIGINFO 1")
+ ? qr/DETAIL: Signal sent by PID \d+, UID \d+\.\n/
+ : qr//;
like( $err, qr/psql:<stdin>:2: FATAL: terminating connection due to administrator command
-(?:DETAIL: Signal sent by PID \d+, UID \d+\.\n)?psql:<stdin>:2: server closed the connection unexpectedly
+${detail_re}psql:<stdin>:2: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
psql:<stdin>:2: error: connection to server was lost/,
disable_sigpipe_trap(void)
{
#ifndef WIN32
- pqsignal(SIGPIPE, SIG_IGN);
+ pqsignal(SIGPIPE, PG_SIG_IGN);
#endif
}
restore_sigpipe_trap(void)
{
#ifndef WIN32
- pqsignal(SIGPIPE, always_ignore_sigpipe ? SIG_IGN : SIG_DFL);
+ pqsignal(SIGPIPE, always_ignore_sigpipe ? PG_SIG_IGN : PG_SIG_DFL);
#endif
}
#endif
/*
- * The following is used as the arg list for signal handlers. Any ports
- * that take something other than an int argument should override this in
- * their pg_config_os.h file. Note that variable names are required
- * because it is used in both the prototypes as well as the definitions.
- * Note also the long name. We expect that this won't collide with
- * other names causing compiler warnings.
+ * Platform independent struct representing additional information about the
+ * received signal. If the system does not support the extended information,
+ * or a field does not apply to the signal, the value is instead reset to the
+ * documented default value.
*/
-#ifndef SIGNAL_ARGS
-#define SIGNAL_ARGS int postgres_signal_arg
-#endif
+typedef struct pg_signal_info
+{
+ uint32_t pid; /* pid of sending process or 0 if unknown */
+ uint32_t uid; /* uid of sending process; only meaningful
+ * when pid is not 0 */
+} pg_signal_info;
+
+/*
+ * The following is used as the arg list for signal handlers. These days we
+ * use the same argument to all signal handlers and hide the difference
+ * between platforms in wrapper functions.
+ *
+ * SIGNAL_ARGS just exists separately from the pqsignal() definition for
+ * historical reasons.
+ */
+#define SIGNAL_ARGS int postgres_signal_arg, const pg_signal_info *pg_siginfo
/*
* When there is no sigsetjmp, its functionality is provided by plain
#else
#define pqsignal pqsignal_be
#endif
+
+#define PG_SIG_DFL (pqsigfunc) (pg_funcptr_t) SIG_DFL
+#define PG_SIG_IGN (pqsigfunc) (pg_funcptr_t) SIG_IGN
typedef void (*pqsigfunc) (SIGNAL_ARGS);
extern void pqsignal(int signo, pqsigfunc func);
* is to ensure that no in-tree code accidentally calls this version.)
*/
#undef pqsignal
-extern pqsigfunc pqsignal(int signo, pqsigfunc func);
-pqsigfunc
-pqsignal(int signo, pqsigfunc func)
+typedef void (*pqsigfunc_legacy) (int postgres_signal_arg);
+extern pqsigfunc_legacy pqsignal(int signo, pqsigfunc_legacy func);
+
+pqsigfunc_legacy
+pqsignal(int signo, pqsigfunc_legacy func)
{
#ifndef WIN32
struct sigaction act,
#define PG_NSIG (64) /* XXX: wild guess */
#endif
+#if !(defined(WIN32) && defined(FRONTEND))
+#define USE_SIGACTION
+#endif
+
+#if defined(USE_SIGACTION) && defined(HAVE_SA_SIGINFO)
+#define USE_SIGINFO
+#endif
+
/* Check a couple of common signals to make sure PG_NSIG is accurate. */
StaticAssertDecl(SIGUSR2 < PG_NSIG, "SIGUSR2 >= PG_NSIG");
StaticAssertDecl(SIGHUP < PG_NSIG, "SIGHUP >= PG_NSIG");
*
* This wrapper also handles restoring the value of errno.
*/
-#if !defined(FRONTEND) && defined(HAVE_SA_SIGINFO)
+#if defined(USE_SIGACTION) && defined(USE_SIGINFO)
static void
-wrapper_handler(int signo, siginfo_t * info, void *context)
-#else
+wrapper_handler(int postgres_signal_arg, siginfo_t * info, void *context)
+#else /* no USE_SIGINFO */
static void
-wrapper_handler(SIGNAL_ARGS)
+wrapper_handler(int postgres_signal_arg)
#endif
{
int save_errno = errno;
-#if !defined(FRONTEND) && defined(HAVE_SA_SIGINFO)
- /* SA_SIGINFO signature uses signo, not SIGNAL_ARGS macro */
- int postgres_signal_arg = signo;
-#endif
+ pg_signal_info pg_info;
Assert(postgres_signal_arg > 0);
Assert(postgres_signal_arg < PG_NSIG);
if (unlikely(MyProcPid != (int) getpid()))
{
- pqsignal(postgres_signal_arg, SIG_DFL);
+ pqsignal(postgres_signal_arg, PG_SIG_DFL);
raise(postgres_signal_arg);
return;
}
+#endif
#ifdef HAVE_SA_SIGINFO
- if (signo == SIGTERM && info)
- {
- ProcDieSenderPid = info->si_pid;
- ProcDieSenderUid = info->si_uid;
- }
-#endif
+
+ /*
+ * If supported by the system, forward interesting information from the
+ * system's extended signal information to our platform independent
+ * format.
+ */
+ pg_info.pid = info->si_pid;
+ pg_info.uid = info->si_uid;
+#else
+
+ /*
+ * Otherwise forward values indicating that we do not have the
+ * information.
+ */
+ pg_info.pid = 0;
+ pg_info.uid = 0;
#endif
- (*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg);
+ (*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg, &pg_info);
errno = save_errno;
}
void
pqsignal(int signo, pqsigfunc func)
{
-#if !(defined(WIN32) && defined(FRONTEND))
+#ifdef USE_SIGACTION
struct sigaction act;
+#else
+ void (*wrapper_func_ptr) (int);
#endif
- bool use_wrapper = false;
+ bool is_ign = func == PG_SIG_IGN;
+ bool is_dfl = func == PG_SIG_DFL;
Assert(signo > 0);
Assert(signo < PG_NSIG);
- if (func != SIG_IGN && func != SIG_DFL)
+ /* set up indirection handler */
+ if (!(is_ign || is_dfl))
{
pqsignal_handlers[signo] = func; /* assumed atomic */
- use_wrapper = true;
}
-#if !(defined(WIN32) && defined(FRONTEND))
+ /*
+ * Configure system to either ignore/reset the signal handler, or to
+ * forward it to wrapper_handler.
+ */
+#ifdef USE_SIGACTION
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
-#if !defined(FRONTEND) && defined(HAVE_SA_SIGINFO)
- if (use_wrapper)
+
+ if (is_ign)
+ act.sa_handler = SIG_IGN;
+ else if (is_dfl)
+ act.sa_handler = SIG_DFL;
+#ifdef USE_SIGINFO
+ else
{
act.sa_sigaction = wrapper_handler;
act.sa_flags |= SA_SIGINFO;
}
- else
- act.sa_handler = func;
#else
- act.sa_handler = use_wrapper ? wrapper_handler : func;
+ else
+ act.sa_handler = wrapper_handler;
#endif
#ifdef SA_NOCLDSTOP
#endif
if (sigaction(signo, &act, NULL) < 0)
Assert(false); /* probably indicates coding error */
-#else
- /* Forward to Windows native signal system. */
- if (signal(signo, use_wrapper ? wrapper_handler : func) == SIG_ERR)
+#else /* no USE_SIGACTION */
+
+ /*
+ * Forward to Windows native signal system, we need to send this though
+ * wrapper handler as it it needs to take single argument only.
+ */
+ if (is_ign)
+ wrapper_func_ptr = SIG_IGN;
+ else if (is_dfl)
+ wrapper_func_ptr = SIG_DFL;
+ else
+ wrapper_func_ptr = wrapper_handler;
+
+ if (signal(signo, wrapper_func_ptr) == SIG_ERR)
Assert(false); /* probably indicates coding error */
#endif
}
{
remove_temp();
- pqsignal(postgres_signal_arg, SIG_DFL);
+ pqsignal(postgres_signal_arg, PG_SIG_DFL);
raise(postgres_signal_arg);
}
pg_sha256_ctx
pg_sha384_ctx
pg_sha512_ctx
+pg_signal_info
pg_snapshot
pg_special_case
pg_stack_base_t