<!--
-$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.82 2001/09/21 03:32:35 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v 1.83 2001/09/21 17:06:12 tgl Exp $
-->
<Chapter Id="runtime">
</varlistentry>
<varlistentry>
+ <term><varname>AUTHENTICATION_TIMEOUT</varname> (<type>integer</type>)</term>
+ <listitem>
+ <para>
+ Maximum time to complete client authentication, in seconds.
+ If a would-be client has not completed the authentication protocol
+ in this much time, the server unceremoniously breaks the connection.
+ This prevents hung clients from occupying a connection indefinitely.
+ This option can only be set at server start or in the
+ <filename>postgresql.conf</filename> file.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<indexterm>
<primary>deadlock</primary>
<secondary>timeout</secondary>
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/libpq/pqsignal.c,v 1.23 2001/09/08 01:10:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/libpq/pqsignal.c,v 1.24 2001/09/21 17:06:12 tgl Exp $
*
* NOTES
* This shouldn't be in libpq, but the monitor and some other
* signals that should never be turned off.
*
* AuthBlockSig is the set of signals to block during authentication;
- * it's essentially BlockSig minus SIGTERM and SIGQUIT.
+ * it's essentially BlockSig minus SIGTERM, SIGQUIT, SIGALRM.
*
* UnBlockSig is the set of signals to block when we don't want to block
* signals (is this ever nonzero??)
#ifdef SIGQUIT
sigdelset(&AuthBlockSig, SIGQUIT);
#endif
+#ifdef SIGALRM
+ sigdelset(&AuthBlockSig, SIGALRM);
+#endif
#else
UnBlockSig = 0;
BlockSig = sigmask(SIGHUP) | sigmask(SIGQUIT) |
sigmask(SIGINT) | sigmask(SIGUSR1) |
sigmask(SIGUSR2) | sigmask(SIGCHLD) |
sigmask(SIGWINCH) | sigmask(SIGFPE);
- AuthBlockSig = sigmask(SIGHUP) | sigmask(SIGALRM) |
+ AuthBlockSig = sigmask(SIGHUP) |
sigmask(SIGINT) | sigmask(SIGUSR1) |
sigmask(SIGUSR2) | sigmask(SIGCHLD) |
sigmask(SIGWINCH) | sigmask(SIGFPE);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.241 2001/09/08 01:10:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/postmaster/postmaster.c,v 1.242 2001/09/21 17:06:12 tgl Exp $
*
* NOTES
*
bool EnableSSL = false;
bool SilentMode = false; /* silent mode (-S) */
+int PreAuthDelay = 0;
+int AuthenticationTimeout = 60;
int CheckPointTimeout = 300;
/* Startup/shutdown state */
MyProcPid = getpid();
/*
+ * Initialize libpq and enable reporting of elog errors to the client.
+ * Must do this now because authentication uses libpq to send messages.
+ */
+ pq_init(); /* initialize libpq to talk to client */
+ whereToSendOutput = Remote; /* now safe to elog to client */
+
+ /*
* We arrange for a simple exit(0) if we receive SIGTERM or SIGQUIT
* during any client authentication related communication. Otherwise
* the postmaster cannot shutdown the database FAST or IMMED cleanly
- * if a buggy client blocks a backend during authentication.
+ * if a buggy client blocks a backend during authentication. We also
+ * will exit(0) after a time delay, so that a broken client can't hog
+ * a connection indefinitely.
+ *
+ * PreAuthDelay is a debugging aid for investigating problems in the
+ * authentication cycle: it can be set in postgresql.conf to allow
+ * time to attach to the newly-forked backend with a debugger.
+ * (See also the -W backend switch, which we allow clients to pass
+ * through PGOPTIONS, but it is not honored until after authentication.)
*/
pqsignal(SIGTERM, authdie);
pqsignal(SIGQUIT, authdie);
+ pqsignal(SIGALRM, authdie);
PG_SETMASK(&AuthBlockSig);
+ if (PreAuthDelay > 0)
+ sleep(PreAuthDelay);
+
+ if (! enable_sigalrm_interrupt(AuthenticationTimeout * 1000))
+ elog(FATAL, "DoBackend: Unable to set timer for auth timeout");
+
/*
* Receive the startup packet (which might turn out to be a cancel
* request packet); then perform client authentication.
ClientAuthentication(MyProcPort); /* might not return, if failure */
/*
- * Done with authentication. Prevent SIGTERM/SIGQUIT again until
- * backend startup is complete.
+ * Done with authentication. Disable timeout, and prevent SIGTERM/SIGQUIT
+ * again until backend startup is complete.
*/
+ if (! disable_sigalrm_interrupt())
+ elog(FATAL, "DoBackend: Unable to disable timer for auth timeout");
PG_SETMASK(&BlockSig);
/*
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.107 2001/09/07 00:27:29 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v 1.108 2001/09/21 17:06:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
waitingForLock = false;
/* Turn off the deadlock timer, if it's still running (see ProcSleep) */
-#ifndef __BEOS__
- {
- struct itimerval timeval,
- dummy;
-
- MemSet(&timeval, 0, sizeof(struct itimerval));
- setitimer(ITIMER_REAL, &timeval, &dummy);
- }
-#else
- /* BeOS doesn't have setitimer, but has set_alarm */
- set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM);
-#endif /* __BEOS__ */
+ disable_sigalrm_interrupt();
/* Unlink myself from the wait queue, if on it (might not be anymore!) */
LockLockTable();
bool early_deadlock = false;
PROC *proc;
int i;
-#ifndef __BEOS__
- struct itimerval timeval,
- dummy;
-#else
- bigtime_t time_interval;
-#endif
/*
* Determine where to add myself in the wait queue.
*
* By delaying the check until we've waited for a bit, we can avoid
* running the rather expensive deadlock-check code in most cases.
- *
- * Need to zero out struct to set the interval and the microseconds
- * fields to 0.
*/
-#ifndef __BEOS__
- MemSet(&timeval, 0, sizeof(struct itimerval));
- timeval.it_value.tv_sec = DeadlockTimeout / 1000;
- timeval.it_value.tv_usec = (DeadlockTimeout % 1000) * 1000;
- if (setitimer(ITIMER_REAL, &timeval, &dummy))
+ if (! enable_sigalrm_interrupt(DeadlockTimeout))
elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
-#else
- time_interval = DeadlockTimeout * 1000000; /* usecs */
- if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
- elog(FATAL, "ProcSleep: Unable to set timer for process wakeup");
-#endif
/*
* If someone wakes us between SpinRelease and IpcSemaphoreLock,
/*
* Disable the timer, if it's still running
*/
-#ifndef __BEOS__
- MemSet(&timeval, 0, sizeof(struct itimerval));
- if (setitimer(ITIMER_REAL, &timeval, &dummy))
- elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
-#else
- if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
+ if (! disable_sigalrm_interrupt())
elog(FATAL, "ProcSleep: Unable to disable timer for process wakeup");
-#endif
/*
* Now there is nothing for LockWaitCancel to do.
/*****************************************************************************
+ * SIGALRM interrupt support
+ *
+ * Maybe these should be in pqsignal.c?
+ *****************************************************************************/
+
+/*
+ * Enable the SIGALRM interrupt to fire after the specified delay
+ *
+ * Delay is given in milliseconds. Caller should be sure a SIGALRM
+ * signal handler is installed before this is called.
+ *
+ * Returns TRUE if okay, FALSE on failure.
+ */
+bool
+enable_sigalrm_interrupt(int delayms)
+{
+#ifndef __BEOS__
+ struct itimerval timeval,
+ dummy;
+
+ MemSet(&timeval, 0, sizeof(struct itimerval));
+ timeval.it_value.tv_sec = delayms / 1000;
+ timeval.it_value.tv_usec = (delayms % 1000) * 1000;
+ if (setitimer(ITIMER_REAL, &timeval, &dummy))
+ return false;
+#else
+ /* BeOS doesn't have setitimer, but has set_alarm */
+ bigtime_t time_interval;
+
+ time_interval = delayms * 1000; /* usecs */
+ if (set_alarm(time_interval, B_ONE_SHOT_RELATIVE_ALARM) < 0)
+ return false;
+#endif
+
+ return true;
+}
+
+/*
+ * Disable the SIGALRM interrupt, if it has not yet fired
+ *
+ * Returns TRUE if okay, FALSE on failure.
+ */
+bool
+disable_sigalrm_interrupt(void)
+{
+#ifndef __BEOS__
+ struct itimerval timeval,
+ dummy;
+
+ MemSet(&timeval, 0, sizeof(struct itimerval));
+ if (setitimer(ITIMER_REAL, &timeval, &dummy))
+ return false;
+#else
+ /* BeOS doesn't have setitimer, but has set_alarm */
+ if (set_alarm(B_INFINITE_TIMEOUT, B_PERIODIC_ALARM) < 0)
+ return false;
+#endif
+
+ return true;
+}
+
+
+/*****************************************************************************
*
*****************************************************************************/
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.232 2001/09/08 01:10:20 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.233 2001/09/21 17:06:12 tgl Exp $
*
* NOTES
* this is the "main" module of the postgres backend and
}
/*
- * Shutdown signal from postmaster during client authentication.
+ * Timeout or shutdown signal from postmaster during client authentication.
* Simply exit(0).
*
* XXX: possible future improvement: try to send a message indicating
* why we are disconnecting. Problem is to be sure we don't block while
- * doing so nor mess up the authentication message exchange.
+ * doing so, nor mess up the authentication message exchange.
*/
void
authdie(SIGNAL_ARGS)
SetProcessingMode(InitProcessing);
/*
- * If under postmaster, initialize libpq and enable reporting of
- * elog errors to the client.
- */
- if (IsUnderPostmaster)
- {
- pq_init(); /* initialize libpq at backend startup */
- whereToSendOutput = Remote; /* now safe to elog to client */
- }
-
- /*
* Set default values for command-line options.
*/
Noversion = false;
if (!IsUnderPostmaster)
{
puts("\nPOSTGRES backend interactive interface ");
- puts("$Revision: 1.232 $ $Date: 2001/09/08 01:10:20 $\n");
+ puts("$Revision: 1.233 $ $Date: 2001/09/21 17:06:12 $\n");
}
/*
* Support for grand unified configuration scheme, including SET
* command, configuration file, and command line options.
*
- * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.50 2001/09/21 03:32:35 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/misc/guc.c,v 1.51 2001/09/21 17:06:12 tgl Exp $
*
* Copyright 2000 by PostgreSQL Global Development Group
* Written by Peter Eisentraut <peter_e@gmx.net>.
/* XXX these should be in other modules' header files */
extern bool Log_connections;
+extern int PreAuthDelay;
+extern int AuthenticationTimeout;
extern int CheckPointTimeout;
extern int CommitDelay;
extern int CommitSiblings;
{"max_locks_per_transaction", PGC_POSTMASTER, &max_locks_per_xact,
64, 10, INT_MAX, NULL, NULL},
+ {"authentication_timeout", PGC_SIGHUP, &AuthenticationTimeout,
+ 60, 1, 600, NULL, NULL},
+
+ {"pre_auth_delay", PGC_SIGHUP, &PreAuthDelay,
+ 0, 0, 60, NULL, NULL},
+
{"checkpoint_segments", PGC_SIGHUP, &CheckPointSegments,
3, 1, INT_MAX, NULL, NULL},
#
#dynamic_library_path = '$libdir'
#australian_timezones = false
+#authentication_timeout = 60 # min 1, max 600
#deadlock_timeout = 1000
#default_transaction_isolation = 'read committed'
#max_expr_depth = 10000 # min 10
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: proc.h,v 1.46 2001/09/07 00:27:30 tgl Exp $
+ * $Id: proc.h,v 1.47 2001/09/21 17:06:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void ProcCancelWaitForSignal(void);
extern void ProcSendSignal(BackendId procId);
+extern bool enable_sigalrm_interrupt(int delayms);
+extern bool disable_sigalrm_interrupt(void);
+
#endif /* PROC_H */