Hi,
To be reviewed easily, I'm splitting Synch Rep patch into some pieces.
Attached is a patch of signal handling changes for Synch Rep.
http://archives.postgresql.org/pgsql-hackers/2008-09/msg00950.php
Though I've posted the WIP patch previously, this is a finished one.
Please feel free to comment on it.
Regards,
--
Fujii Masao
NIPPON TELEGRAPH AND TELEPHONE CORPORATION
NTT Open Source Software Center
Index: src/backend/access/transam/twophase.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/transam/twophase.c,v
retrieving revision 1.46
diff -c -r1.46 twophase.c
*** src/backend/access/transam/twophase.c 20 Oct 2008 19:18:18 -0000 1.46
--- src/backend/access/transam/twophase.c 27 Oct 2008 01:59:57 -0000
***************
*** 285,290 ****
--- 285,291 ----
gxact->proc.databaseId = databaseid;
gxact->proc.roleId = owner;
gxact->proc.inCommit = false;
+ gxact->proc.signalFlags = 0;
gxact->proc.vacuumFlags = 0;
gxact->proc.lwWaiting = false;
gxact->proc.lwExclusive = false;
Index: src/backend/commands/async.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/commands/async.c,v
retrieving revision 1.141
diff -c -r1.141 async.c
*** src/backend/commands/async.c 30 Aug 2008 01:39:13 -0000 1.141
--- src/backend/commands/async.c 27 Oct 2008 01:59:57 -0000
***************
*** 915,923 ****
* a frontend command. Signal handler execution of inbound notifies
* is disabled until the next EnableNotifyInterrupt call.
*
! * The SIGUSR1 signal handler also needs to call this, so as to
! * prevent conflicts if one signal interrupts the other. So we
! * must return the previous state of the flag.
*/
bool
DisableNotifyInterrupt(void)
--- 915,924 ----
* a frontend command. Signal handler execution of inbound notifies
* is disabled until the next EnableNotifyInterrupt call.
*
! * This also needs to be called when SIGUSR1 with
! * PROCSIGNAL_CATCHUP_INTERRUPT is received, so as to prevent conflicts
! * if one signal interrupts the other. So we must return the previous
! * state of the flag.
*/
bool
DisableNotifyInterrupt(void)
***************
*** 954,960 ****
nulls[Natts_pg_listener];
bool catchup_enabled;
! /* Must prevent SIGUSR1 interrupt while I am running */
catchup_enabled = DisableCatchupInterrupt();
if (Trace_notify)
--- 955,961 ----
nulls[Natts_pg_listener];
bool catchup_enabled;
! /* Must prevent catchup interrupt while I am running */
catchup_enabled = DisableCatchupInterrupt();
if (Trace_notify)
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.84
diff -c -r1.84 autovacuum.c
*** src/backend/postmaster/autovacuum.c 13 Aug 2008 00:07:50 -0000 1.84
--- src/backend/postmaster/autovacuum.c 27 Oct 2008 01:59:57 -0000
***************
*** 1480,1486 ****
pqsignal(SIGALRM, handle_sig_alarm);
pqsignal(SIGPIPE, SIG_IGN);
! pqsignal(SIGUSR1, CatchupInterruptHandler);
/* We don't listen for async notifies */
pqsignal(SIGUSR2, SIG_IGN);
pqsignal(SIGFPE, FloatExceptionHandler);
--- 1480,1486 ----
pqsignal(SIGALRM, handle_sig_alarm);
pqsignal(SIGPIPE, SIG_IGN);
! pqsignal(SIGUSR1, proc_sigusr1_handler);
/* We don't listen for async notifies */
pqsignal(SIGUSR2, SIG_IGN);
pqsignal(SIGFPE, FloatExceptionHandler);
Index: src/backend/storage/ipc/sinval.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/ipc/sinval.c,v
retrieving revision 1.86
diff -c -r1.86 sinval.c
*** src/backend/storage/ipc/sinval.c 19 Jun 2008 21:32:56 -0000 1.86
--- src/backend/storage/ipc/sinval.c 27 Oct 2008 01:59:57 -0000
***************
*** 27,33 ****
* need a way to give an idle backend a swift kick in the rear and make
* it catch up before the sinval queue overflows and forces it to go
* through a cache reset exercise. This is done by sending SIGUSR1
! * to any backend that gets too far behind.
*
* State for catchup events consists of two flags: one saying whether
* the signal handler is currently allowed to call ProcessCatchupEvent
--- 27,34 ----
* need a way to give an idle backend a swift kick in the rear and make
* it catch up before the sinval queue overflows and forces it to go
* through a cache reset exercise. This is done by sending SIGUSR1
! * with PROCSIGNAL_CATCHUP_INTERRUPT to any backend that gets too far
! * behind.
*
* State for catchup events consists of two flags: one saying whether
* the signal handler is currently allowed to call ProcessCatchupEvent
***************
*** 144,152 ****
/*
! * CatchupInterruptHandler
*
! * This is the signal handler for SIGUSR1.
*
* If we are idle (catchupInterruptEnabled is set), we can safely
* invoke ProcessCatchupEvent directly. Otherwise, just set a flag
--- 145,154 ----
/*
! * HandleCatchupInterrupt
*
! * This is called when SIGUSR1 with PROCSIGNAL_CATCHUP_INTERRUPT is
! * received.
*
* If we are idle (catchupInterruptEnabled is set), we can safely
* invoke ProcessCatchupEvent directly. Otherwise, just set a flag
***************
*** 156,168 ****
* since there's no longer any reason to do anything.)
*/
void
! CatchupInterruptHandler(SIGNAL_ARGS)
{
- int save_errno = errno;
-
/*
! * Note: this is a SIGNAL HANDLER. You must be very wary what you do
! * here.
*/
/* Don't joggle the elbow of proc_exit */
--- 158,168 ----
* since there's no longer any reason to do anything.)
*/
void
! HandleCatchupInterrupt(void)
{
/*
! * Note: this is called by a SIGNAL HANDLER.
! * You must be very wary what you do here.
*/
/* Don't joggle the elbow of proc_exit */
***************
*** 216,223 ****
*/
catchupInterruptOccurred = 1;
}
-
- errno = save_errno;
}
/*
--- 216,221 ----
***************
*** 289,295 ****
/*
* ProcessCatchupEvent
*
! * Respond to a catchup event (SIGUSR1) from another backend.
*
* This is called either directly from the SIGUSR1 signal handler,
* or the next time control reaches the outer idle loop (assuming
--- 287,294 ----
/*
* ProcessCatchupEvent
*
! * Respond to a catchup event (SIGUSR1 with PROCSIGNAL_CATCHUP_INTERRUPT)
! * from another backend.
*
* This is called either directly from the SIGUSR1 signal handler,
* or the next time control reaches the outer idle loop (assuming
Index: src/backend/storage/ipc/sinvaladt.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/ipc/sinvaladt.c,v
retrieving revision 1.74
diff -c -r1.74 sinvaladt.c
*** src/backend/storage/ipc/sinvaladt.c 18 Jul 2008 14:45:48 -0000 1.74
--- src/backend/storage/ipc/sinvaladt.c 27 Oct 2008 01:59:57 -0000
***************
*** 655,661 ****
LWLockRelease(SInvalReadLock);
LWLockRelease(SInvalWriteLock);
elog(DEBUG4, "sending sinval catchup signal to PID %d", (int) his_pid);
! kill(his_pid, SIGUSR1);
if (callerHasWriteLock)
LWLockAcquire(SInvalWriteLock, LW_EXCLUSIVE);
}
--- 655,661 ----
LWLockRelease(SInvalReadLock);
LWLockRelease(SInvalWriteLock);
elog(DEBUG4, "sending sinval catchup signal to PID %d", (int) his_pid);
! SendProcSignal(his_pid, PROCSIGNAL_CATCHUP_INTERRUPT);
if (callerHasWriteLock)
LWLockAcquire(SInvalWriteLock, LW_EXCLUSIVE);
}
Index: src/backend/storage/lmgr/proc.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v
retrieving revision 1.201
diff -c -r1.201 proc.c
*** src/backend/storage/lmgr/proc.c 9 Jun 2008 18:23:05 -0000 1.201
--- src/backend/storage/lmgr/proc.c 27 Oct 2008 01:59:58 -0000
***************
*** 88,93 ****
--- 88,95 ----
static void AuxiliaryProcKill(int code, Datum arg);
static bool CheckStatementTimeout(void);
+ static PGPROC *AuxiliaryPidGetProc(int pid);
+
/*
* Report shared-memory space needed by InitProcGlobal.
***************
*** 291,296 ****
--- 293,299 ----
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inCommit = false;
+ MyProc->signalFlags = 0;
MyProc->vacuumFlags = 0;
if (IsAutoVacuumWorkerProcess())
MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM;
***************
*** 430,435 ****
--- 433,439 ----
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
MyProc->inCommit = false;
+ MyProc->signalFlags = 0;
/* we don't set the "is autovacuum" flag in the launcher */
MyProc->vacuumFlags = 0;
MyProc->lwWaiting = false;
***************
*** 1281,1286 ****
--- 1285,1377 ----
PGSemaphoreUnlock(&proc->sem);
}
+ /*
+ * SendProcSignal - send a signal with a reason to a process
+ * (such as backend, autovacuum worker and auxiliary process)
+ * identified by PID.
+ */
+ void
+ SendProcSignal(int pid, uint8 reason)
+ {
+ PGPROC *proc = NULL;
+
+ /*
+ * If a given pid is not for a backend or an auxiliary process,
+ * do nothing.
+ */
+ if ((proc = BackendPidGetProc(pid)) == NULL
+ && (proc = AuxiliaryPidGetProc(pid)) == NULL)
+ return;
+
+ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
+ proc->signalFlags |= reason;
+
+ LWLockRelease(ProcArrayLock);
+
+ /* Send SIGUSR1 to a process */
+ kill(pid, SIGUSR1);
+ }
+
+ /*
+ * CheckProcSignal - check to see if a particular reason has been
+ * signaled, and clear the signal flag. Should be called after
+ * receiving SIGUSR1.
+ */
+ bool
+ CheckProcSignal(uint8 reason)
+ {
+ LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+
+ /* Careful here --- don't clear flag if we haven't seen it set */
+ if (MyProc->signalFlags & reason)
+ {
+ MyProc->signalFlags &= ~reason;
+ LWLockRelease(ProcArrayLock);
+ return true;
+ }
+
+ LWLockRelease(ProcArrayLock);
+
+ return false;
+ }
+
+ /*
+ * AuxiliaryPidGetProc - get an auxiliary process's PGPROC given its PID
+ *
+ * Returns NULL if not found. Note that it is up to the caller to be
+ * sure that the question remains meaningful for long enough for the
+ * answer to be used ...
+ */
+ static PGPROC *
+ AuxiliaryPidGetProc(int pid)
+ {
+ PGPROC *result = NULL;
+ int proctype;
+
+ if (pid == 0)
+ return NULL;
+
+ LWLockAcquire(ProcArrayLock, LW_SHARED);
+
+ for (proctype = 0; proctype < NUM_AUXILIARY_PROCS; proctype++)
+ {
+ PGPROC *proc = &AuxiliaryProcs[proctype];
+
+ if (proc->pid == 0)
+ break;
+
+ if (proc->pid == pid)
+ {
+ result = proc;
+ break;
+ }
+ }
+
+ LWLockRelease(ProcArrayLock);
+
+ return result;
+ }
/*****************************************************************************
* SIGALRM interrupt support
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/tcop/postgres.c,v
retrieving revision 1.557
diff -c -r1.557 postgres.c
*** src/backend/tcop/postgres.c 30 Sep 2008 10:52:13 -0000 1.557
--- src/backend/tcop/postgres.c 27 Oct 2008 01:59:58 -0000
***************
*** 2433,2438 ****
--- 2433,2457 ----
*/
/*
+ * proc_sigusr1_handler - handle signal conditions.
+ */
+ void
+ proc_sigusr1_handler(SIGNAL_ARGS)
+ {
+ int save_errno = errno;
+
+ if (CheckProcSignal(PROCSIGNAL_CATCHUP_INTERRUPT))
+ {
+ /*
+ * Catchup interrupt has been sent.
+ */
+ HandleCatchupInterrupt();
+ }
+
+ errno = save_errno;
+ }
+
+ /*
* quickdie() occurs when signalled SIGQUIT by the postmaster.
*
* Some backend has bought the farm,
***************
*** 3176,3182 ****
* of output during who-knows-what operation...
*/
pqsignal(SIGPIPE, SIG_IGN);
! pqsignal(SIGUSR1, CatchupInterruptHandler);
pqsignal(SIGUSR2, NotifyInterruptHandler);
pqsignal(SIGFPE, FloatExceptionHandler);
--- 3195,3201 ----
* of output during who-knows-what operation...
*/
pqsignal(SIGPIPE, SIG_IGN);
! pqsignal(SIGUSR1, proc_sigusr1_handler);
pqsignal(SIGUSR2, NotifyInterruptHandler);
pqsignal(SIGFPE, FloatExceptionHandler);
Index: src/include/storage/proc.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/proc.h,v
retrieving revision 1.106
diff -c -r1.106 proc.h
*** src/include/storage/proc.h 15 Apr 2008 20:28:47 -0000 1.106
--- src/include/storage/proc.h 27 Oct 2008 01:59:58 -0000
***************
*** 38,43 ****
--- 38,46 ----
TransactionId xids[PGPROC_MAX_CACHED_SUBXIDS];
};
+ /* Flags for PGPROC->signalFlags */
+ #define PROCSIGNAL_CATCHUP_INTERRUPT 0x01 /* catchup interrupt */
+
/* Flags for PGPROC->vacuumFlags */
#define PROC_IS_AUTOVACUUM 0x01 /* is it an autovac worker? */
#define PROC_IN_VACUUM 0x02 /* currently running lazy vacuum */
***************
*** 91,96 ****
--- 94,100 ----
bool inCommit; /* true if within commit critical section */
+ uint8 signalFlags; /* signal-related flags, see above */
uint8 vacuumFlags; /* vacuum-related flags, see above */
/* Info about LWLock the process is currently waiting for, if any. */
***************
*** 171,176 ****
--- 175,183 ----
extern void ProcWaitForSignal(void);
extern void ProcSendSignal(int pid);
+ extern void SendProcSignal(int pid, uint8 reason);
+ extern bool CheckProcSignal(uint8 reason);
+
extern bool enable_sig_alarm(int delayms, bool is_statement_timeout);
extern bool disable_sig_alarm(bool is_statement_timeout);
extern void handle_sig_alarm(SIGNAL_ARGS);
Index: src/include/storage/sinval.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/storage/sinval.h,v
retrieving revision 1.48
diff -c -r1.48 sinval.h
*** src/include/storage/sinval.h 19 Jun 2008 21:32:56 -0000 1.48
--- src/include/storage/sinval.h 27 Oct 2008 01:59:58 -0000
***************
*** 90,96 ****
void (*resetFunction) (void));
/* signal handler for catchup events (SIGUSR1) */
! extern void CatchupInterruptHandler(SIGNAL_ARGS);
/*
* enable/disable processing of catchup events directly from signal handler.
--- 90,96 ----
void (*resetFunction) (void));
/* signal handler for catchup events (SIGUSR1) */
! extern void HandleCatchupInterrupt(void);
/*
* enable/disable processing of catchup events directly from signal handler.
Index: src/include/tcop/tcopprot.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/tcop/tcopprot.h,v
retrieving revision 1.93
diff -c -r1.93 tcopprot.h
*** src/include/tcop/tcopprot.h 10 Mar 2008 12:55:13 -0000 1.93
--- src/include/tcop/tcopprot.h 27 Oct 2008 01:59:58 -0000
***************
*** 56,61 ****
--- 56,62 ----
extern bool assign_max_stack_depth(int newval, bool doit, GucSource source);
+ extern void proc_sigusr1_handler(SIGNAL_ARGS);
extern void die(SIGNAL_ARGS);
extern void quickdie(SIGNAL_ARGS);
extern void authdie(SIGNAL_ARGS);
--
Sent via pgsql-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers