/* Global variables */
-sigset_t UnBlockSig,
+sigset_t SleepSig,
+ UnBlockSig,
BlockSig,
StartupBlockSig;
void
pqinitmask(void)
{
+ sigemptyset(&SleepSig);
sigemptyset(&UnBlockSig);
/* First set all signals, then clear some. */
#ifdef SIGALRM
sigdelset(&StartupBlockSig, SIGALRM);
#endif
+
+ sigaddset(&UnBlockSig, SIGURG);
}
/*
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
+ pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, avl_sigusr2_handler);
+ pqsignal(SIGURG, latch_sigurg_handler);
pqsignal(SIGFPE, FloatExceptionHandler);
pqsignal(SIGCHLD, SIG_DFL);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGURG, latch_sigurg_handler);
pqsignal(SIGFPE, FloatExceptionHandler);
pqsignal(SIGCHLD, SIG_DFL);
pg_memory_barrier();
slot->pid = 0;
slot->in_use = false;
+ /* FIXME: shouldn't this use SetLatch() or something */
if (notify_pid != 0)
kill(notify_pid, SIGUSR1);
*/
pqsignal(SIGINT, StatementCancelHandler);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
+ pqsignal(SIGURG, latch_sigurg_handler);
pqsignal(SIGFPE, FloatExceptionHandler);
/* XXX Any other handlers needed here? */
{
pqsignal(SIGINT, SIG_IGN);
pqsignal(SIGUSR1, bgworker_sigusr1_handler);
+ pqsignal(SIGURG, latch_sigurg_handler);
pqsignal(SIGFPE, SIG_IGN);
}
pqsignal(SIGTERM, bgworker_die);
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGURG, latch_sigurg_handler);
/*
* Reset some signals that are accepted by postmaster but not here
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SignalHandlerForShutdownRequest);
+ pqsignal(SIGURG, latch_sigurg_handler);
/*
* Reset some signals that are accepted by postmaster but not here
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, StartupProcTriggerHandler);
+ pqsignal(SIGURG, latch_sigurg_handler);
/*
* Reset some signals that are accepted by postmaster but not here
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN); /* not used */
+ pqsignal(SIGURG, latch_sigurg_handler);
/*
* Reset some signals that are accepted by postmaster but not here
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGURG, latch_sigurg_handler);
/* Reset some signals that are accepted by postmaster but not here */
pqsignal(SIGCHLD, SIG_DFL);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, WalSndLastCycleHandler); /* request a last cycle and
* shutdown */
+ pqsignal(SIGURG, latch_sigurg_handler);
/* Reset some signals that are accepted by postmaster but not here */
pqsignal(SIGCHLD, SIG_DFL);
#include <poll.h>
#endif
+#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "port/atomics.h"
InitLatch(Latch *latch)
{
latch->is_set = false;
+ latch->maybe_sleeping = false;
latch->owner_pid = MyProcPid;
latch->is_shared = false;
#endif
latch->is_set = false;
+ latch->maybe_sleeping = false;
latch->owner_pid = 0;
latch->is_shared = true;
}
latch->is_set = true;
+ pg_memory_barrier();
+
+ if (!latch->maybe_sleeping)
+ return;
+
#ifndef WIN32
/*
sendSelfPipeByte();
}
else
- kill(owner_pid, SIGUSR1);
+ kill(owner_pid, SIGURG);
#else
/*
{
/* Only the owner should reset the latch */
Assert(latch->owner_pid == MyProcPid);
+ Assert(latch->maybe_sleeping == false);
latch->is_set = false;
* ordering, so that we cannot miss seeing is_set if a notification
* has already been queued.
*/
+ if (set->latch && !set->latch->is_set)
+ {
+ /* about to sleep on a latch */
+ set->latch->maybe_sleeping = true;
+ pg_memory_barrier();
+ /* and recheck */
+ }
+
if (set->latch && set->latch->is_set)
{
occurred_events->fd = PGINVALID_SOCKET;
occurred_events++;
returned_events++;
+ /* could have been set above */
+ set->latch->maybe_sleeping = false;
+
break;
}
rc = WaitEventSetWaitBlock(set, cur_timeout,
occurred_events, nevents);
+ if (set->latch)
+ {
+ Assert(set->latch->maybe_sleeping);
+ set->latch->maybe_sleeping = false;
+ }
+
if (rc == -1)
break; /* timeout occurred */
else
struct epoll_event *cur_epoll_event;
/* Sleep */
- rc = epoll_wait(set->epoll_fd, set->epoll_ret_events,
- nevents, cur_timeout);
+ rc = epoll_pwait(set->epoll_fd, set->epoll_ret_events,
+ nevents, cur_timeout, &SleepSig);
/* Check return code */
if (rc < 0)
if (cur_event->events == WL_LATCH_SET &&
cur_epoll_event->events & (EPOLLIN | EPOLLERR | EPOLLHUP))
{
+ Assert(set->latch);
+
/* There's data in the self-pipe, clear it. */
drainSelfPipe();
if (waiting)
sendSelfPipeByte();
}
+
+void
+latch_sigurg_handler(SIGNAL_ARGS)
+{
+ if (waiting)
+ sendSelfPipeByte();
+}
+
#endif /* !WIN32 */
/* Send one byte to the self-pipe, to wake up WaitLatch */
SetLatch(MyLatch);
- latch_sigusr1_handler();
+ //latch_sigusr1_handler();
errno = save_errno;
}
pqsignal(SIGPIPE, SIG_IGN);
pqsignal(SIGUSR1, procsignal_sigusr1_handler);
pqsignal(SIGUSR2, SIG_IGN);
+ pqsignal(SIGURG, latch_sigurg_handler);
pqsignal(SIGFPE, FloatExceptionHandler);
/*
#define sigdelset(set, signum) (*(set) &= ~(sigmask(signum)))
#endif /* WIN32 */
-extern sigset_t UnBlockSig,
+extern sigset_t SleepSig,
+ UnBlockSig,
BlockSig,
StartupBlockSig;
typedef struct Latch
{
sig_atomic_t is_set;
+ sig_atomic_t maybe_sleeping;
bool is_shared;
int owner_pid;
#ifdef WIN32
*/
#ifndef WIN32
extern void latch_sigusr1_handler(void);
+extern void latch_sigurg_handler(SIGNAL_ARGS);
#else
#define latch_sigusr1_handler() ((void) 0)
+static inline void latch_sigurg_handler(SIGNAL_ARGS) {}
#endif
#endif /* LATCH_H */