Commit 83709a0d authored by Thomas Munro's avatar Thomas Munro

Use SIGURG rather than SIGUSR1 for latches.

Traditionally, SIGUSR1 has been overloaded for ad-hoc signals,
procsignal.c signals and latch.c wakeups.  Move that last use over to a
new dedicated signal.  SIGURG is normally used to report out-of-band
socket data, but PostgreSQL doesn't use that facility.

The signal handler is now installed in all postmaster children by
InitializeLatchSupport().  Those wishing to disconnect from it should
call ShutdownLatchSupport().

Future patches will use this separation of signals to avoid the need for
a signal handler on some operating systems.

Discussion: https://postgr.es/m/CA+hUKGJjxPDpzBE0a3hyUywBvaZuC89yx3jK9RFZgfv_KHU7gg@mail.gmail.com
parent c8f3bc24
...@@ -713,22 +713,6 @@ bgworker_die(SIGNAL_ARGS) ...@@ -713,22 +713,6 @@ bgworker_die(SIGNAL_ARGS)
MyBgworkerEntry->bgw_type))); MyBgworkerEntry->bgw_type)));
} }
/*
* Standard SIGUSR1 handler for unconnected workers
*
* Here, we want to make sure an unconnected worker will at least heed
* latch activity.
*/
static void
bgworker_sigusr1_handler(SIGNAL_ARGS)
{
int save_errno = errno;
latch_sigusr1_handler();
errno = save_errno;
}
/* /*
* Start a new background worker * Start a new background worker
* *
...@@ -759,6 +743,7 @@ StartBackgroundWorker(void) ...@@ -759,6 +743,7 @@ StartBackgroundWorker(void)
*/ */
if ((worker->bgw_flags & BGWORKER_SHMEM_ACCESS) == 0) if ((worker->bgw_flags & BGWORKER_SHMEM_ACCESS) == 0)
{ {
ShutdownLatchSupport();
dsm_detach_all(); dsm_detach_all();
PGSharedMemoryDetach(); PGSharedMemoryDetach();
} }
...@@ -786,7 +771,7 @@ StartBackgroundWorker(void) ...@@ -786,7 +771,7 @@ StartBackgroundWorker(void)
else else
{ {
pqsignal(SIGINT, SIG_IGN); pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGUSR1, bgworker_sigusr1_handler); pqsignal(SIGUSR1, SIG_IGN);
pqsignal(SIGFPE, SIG_IGN); pqsignal(SIGFPE, SIG_IGN);
} }
pqsignal(SIGTERM, bgworker_die); pqsignal(SIGTERM, bgworker_die);
......
...@@ -656,6 +656,10 @@ PostmasterMain(int argc, char *argv[]) ...@@ -656,6 +656,10 @@ PostmasterMain(int argc, char *argv[])
pqsignal_pm(SIGUSR2, dummy_handler); /* unused, reserve for children */ pqsignal_pm(SIGUSR2, dummy_handler); /* unused, reserve for children */
pqsignal_pm(SIGCHLD, reaper); /* handle child termination */ pqsignal_pm(SIGCHLD, reaper); /* handle child termination */
#ifdef SIGURG
pqsignal_pm(SIGURG, SIG_IGN); /* ignored */
#endif
/* /*
* No other place in Postgres should touch SIGTTIN/SIGTTOU handling. We * No other place in Postgres should touch SIGTTIN/SIGTTOU handling. We
* ignore those signals in a postmaster environment, so that there is no * ignore those signals in a postmaster environment, so that there is no
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
* *
* When SetLatch is called from the same process that owns the latch, * When SetLatch is called from the same process that owns the latch,
* SetLatch writes the byte directly to the pipe. If it's owned by another * SetLatch writes the byte directly to the pipe. If it's owned by another
* process, SIGUSR1 is sent and the signal handler in the waiting process * process, SIGURG is sent and the signal handler in the waiting process
* writes the byte to the pipe on behalf of the signaling process. * writes the byte to the pipe on behalf of the signaling process.
* *
* The Windows implementation uses Windows events that are inherited by all * The Windows implementation uses Windows events that are inherited by all
...@@ -148,6 +148,7 @@ static int selfpipe_writefd = -1; ...@@ -148,6 +148,7 @@ static int selfpipe_writefd = -1;
static int selfpipe_owner_pid = 0; static int selfpipe_owner_pid = 0;
/* Private function prototypes */ /* Private function prototypes */
static void latch_sigurg_handler(SIGNAL_ARGS);
static void sendSelfPipeByte(void); static void sendSelfPipeByte(void);
static void drainSelfPipe(void); static void drainSelfPipe(void);
#endif /* WIN32 */ #endif /* WIN32 */
...@@ -244,6 +245,8 @@ InitializeLatchSupport(void) ...@@ -244,6 +245,8 @@ InitializeLatchSupport(void)
/* Tell fd.c about these two long-lived FDs */ /* Tell fd.c about these two long-lived FDs */
ReserveExternalFD(); ReserveExternalFD();
ReserveExternalFD(); ReserveExternalFD();
pqsignal(SIGURG, latch_sigurg_handler);
#else #else
/* currently, nothing to do here for Windows */ /* currently, nothing to do here for Windows */
#endif #endif
...@@ -267,6 +270,24 @@ InitializeLatchWaitSet(void) ...@@ -267,6 +270,24 @@ InitializeLatchWaitSet(void)
Assert(latch_pos == LatchWaitSetLatchPos); Assert(latch_pos == LatchWaitSetLatchPos);
} }
void
ShutdownLatchSupport(void)
{
pqsignal(SIGURG, SIG_IGN);
if (LatchWaitSet)
{
FreeWaitEventSet(LatchWaitSet);
LatchWaitSet = NULL;
}
close(selfpipe_readfd);
close(selfpipe_writefd);
selfpipe_readfd = -1;
selfpipe_writefd = -1;
selfpipe_owner_pid = InvalidPid;
}
/* /*
* Initialize a process-local latch. * Initialize a process-local latch.
*/ */
...@@ -335,10 +356,6 @@ InitSharedLatch(Latch *latch) ...@@ -335,10 +356,6 @@ InitSharedLatch(Latch *latch)
* any sort of locking here, meaning that we could fail to detect the error * any sort of locking here, meaning that we could fail to detect the error
* if two processes try to own the same latch at about the same time. If * if two processes try to own the same latch at about the same time. If
* there is any risk of that, caller must provide an interlock to prevent it. * there is any risk of that, caller must provide an interlock to prevent it.
*
* In any process that calls OwnLatch(), make sure that
* latch_sigusr1_handler() is called from the SIGUSR1 signal handler,
* as shared latches use SIGUSR1 for inter-process communication.
*/ */
void void
OwnLatch(Latch *latch) OwnLatch(Latch *latch)
...@@ -562,7 +579,7 @@ SetLatch(Latch *latch) ...@@ -562,7 +579,7 @@ SetLatch(Latch *latch)
sendSelfPipeByte(); sendSelfPipeByte();
} }
else else
kill(owner_pid, SIGUSR1); kill(owner_pid, SIGURG);
#else #else
/* /*
...@@ -1266,7 +1283,7 @@ WaitEventSetWait(WaitEventSet *set, long timeout, ...@@ -1266,7 +1283,7 @@ WaitEventSetWait(WaitEventSet *set, long timeout,
* the pipe-buffer fill up we're still ok, because the pipe is in * the pipe-buffer fill up we're still ok, because the pipe is in
* nonblocking mode. It's unlikely for that to happen, because the * nonblocking mode. It's unlikely for that to happen, because the
* self pipe isn't filled unless we're blocking (waiting = true), or * self pipe isn't filled unless we're blocking (waiting = true), or
* from inside a signal handler in latch_sigusr1_handler(). * from inside a signal handler in latch_sigurg_handler().
* *
* On windows, we'll also notice if there's a pending event for the * On windows, we'll also notice if there's a pending event for the
* latch when blocking, but there's no danger of anything filling up, * latch when blocking, but there's no danger of anything filling up,
...@@ -1934,22 +1951,21 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout, ...@@ -1934,22 +1951,21 @@ WaitEventSetWaitBlock(WaitEventSet *set, int cur_timeout,
} }
#endif #endif
#ifndef WIN32
/* /*
* SetLatch uses SIGUSR1 to wake up the process waiting on the latch. * SetLatch uses SIGURG to wake up the process waiting on the latch.
*
* Wake up WaitLatch, if we're waiting. (We might not be, since SIGUSR1 is
* overloaded for multiple purposes; or we might not have reached WaitLatch
* yet, in which case we don't need to fill the pipe either.)
* *
* NB: when calling this in a signal handler, be sure to save and restore * Wake up WaitLatch, if we're waiting.
* errno around it.
*/ */
#ifndef WIN32 static void
void latch_sigurg_handler(SIGNAL_ARGS)
latch_sigusr1_handler(void)
{ {
int save_errno = errno;
if (waiting) if (waiting)
sendSelfPipeByte(); sendSelfPipeByte();
errno = save_errno;
} }
#endif /* !WIN32 */ #endif /* !WIN32 */
......
...@@ -688,7 +688,5 @@ procsignal_sigusr1_handler(SIGNAL_ARGS) ...@@ -688,7 +688,5 @@ procsignal_sigusr1_handler(SIGNAL_ARGS)
SetLatch(MyLatch); SetLatch(MyLatch);
latch_sigusr1_handler();
errno = save_errno; errno = save_errno;
} }
...@@ -163,6 +163,7 @@ extern void OwnLatch(Latch *latch); ...@@ -163,6 +163,7 @@ extern void OwnLatch(Latch *latch);
extern void DisownLatch(Latch *latch); extern void DisownLatch(Latch *latch);
extern void SetLatch(Latch *latch); extern void SetLatch(Latch *latch);
extern void ResetLatch(Latch *latch); extern void ResetLatch(Latch *latch);
extern void ShutdownLatchSupport(void);
extern WaitEventSet *CreateWaitEventSet(MemoryContext context, int nevents); extern WaitEventSet *CreateWaitEventSet(MemoryContext context, int nevents);
extern void FreeWaitEventSet(WaitEventSet *set); extern void FreeWaitEventSet(WaitEventSet *set);
...@@ -179,14 +180,4 @@ extern int WaitLatchOrSocket(Latch *latch, int wakeEvents, ...@@ -179,14 +180,4 @@ extern int WaitLatchOrSocket(Latch *latch, int wakeEvents,
pgsocket sock, long timeout, uint32 wait_event_info); pgsocket sock, long timeout, uint32 wait_event_info);
extern void InitializeLatchWaitSet(void); extern void InitializeLatchWaitSet(void);
/*
* Unix implementation uses SIGUSR1 for inter-process signaling.
* Win32 doesn't need this.
*/
#ifndef WIN32
extern void latch_sigusr1_handler(void);
#else
#define latch_sigusr1_handler() ((void) 0)
#endif
#endif /* LATCH_H */ #endif /* LATCH_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment