diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index d2af5e63ee87bb0ddac47cfbdb977acdf13ad2fd..995d1ae9d35b9c3f487af69de83a70157fcaf71a 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.430 2008/04/14 17:05:32 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.431 2008/04/15 13:55:11 momjian Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -11848,6 +11848,9 @@ SELECT set_config('log_statement_stats', 'off', false);
    <indexterm>
     <primary>pg_cancel_backend</primary>
    </indexterm>
+   <indexterm>
+    <primary>pg_terminate_backend</primary>
+   </indexterm>
    <indexterm>
     <primary>pg_reload_conf</primary>
    </indexterm>
@@ -11883,6 +11886,13 @@ SELECT set_config('log_statement_stats', 'off', false);
        <entry><type>boolean</type></entry>
        <entry>Cancel a backend's current query</entry>
       </row>
+      <row>
+       <entry>
+        <literal><function>pg_terminate_backend</function>(<parameter>pid</parameter> <type>int</>)</literal>
+        </entry>
+       <entry><type>boolean</type></entry>
+       <entry>Terminate a backend</entry>
+      </row>
       <row>
        <entry>
         <literal><function>pg_reload_conf</function>()</literal>
@@ -11907,9 +11917,10 @@ SELECT set_config('log_statement_stats', 'off', false);
    </para>
 
    <para>
-    <function>pg_cancel_backend</> sends a query cancel
-    (<systemitem>SIGINT</>) signal to a backend process identified by
-    process ID.  The process ID of an active backend can be found from
+    <function>pg_cancel_backend</> and <function>pg_terminate_backend</>
+    send a query cancel (<systemitem>SIGINT</>) signal to a backend process
+    identified by process ID.  The
+    process ID of an active backend can be found from
     the <structfield>procpid</structfield> column in the
     <structname>pg_stat_activity</structname> view, or by listing the
     <command>postgres</command> processes on the server with
diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml
index 1c799d8965b60d60e49474a31d8b1e74ecec0c3e..c5222440fc8231cbb01368ea637dfcd852173fba 100644
--- a/doc/src/sgml/runtime.sgml
+++ b/doc/src/sgml/runtime.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.411 2008/03/31 02:43:14 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/runtime.sgml,v 1.412 2008/04/15 13:55:11 momjian Exp $ -->
 
 <chapter Id="runtime">
  <title>Operating System Environment</title>
@@ -1372,6 +1372,13 @@ $ <userinput>kill -INT `head -1 /usr/local/pgsql/data/postmaster.pid`</userinput
     well.
    </para>
   </important>
+
+  <para>
+   To terminate a session while allowing other sessions to continue, use
+   <function>pg_terminate_backend()</> (<xref
+   linkend="functions-admin-signal-table">) rather than sending a signal
+   to the child process.
+  </para>
  </sect1>
 
  <sect1 id="preventing-server-spoofing">
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index d44e69fb10af1a62cf627a823ef94f9366d1a088..60519bd8a95cf2ee86508268b4a9e29c9bc9d93e 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.548 2008/04/02 18:31:50 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/postgres.c,v 1.549 2008/04/15 13:55:11 momjian Exp $
  *
  * NOTES
  *	  this is the "main" module of the postgres backend and
@@ -2541,7 +2541,8 @@ StatementCancelHandler(SIGNAL_ARGS)
 		 * waiting for input, however.
 		 */
 		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
-			CritSectionCount == 0 && !DoingCommandRead)
+			CritSectionCount == 0 &&
+			(!DoingCommandRead || MyProc->terminate))
 		{
 			/* bump holdoff count to make ProcessInterrupts() a no-op */
 			/* until we are done getting ready for it */
@@ -2621,6 +2622,10 @@ ProcessInterrupts(void)
 			ereport(ERROR,
 					(errcode(ERRCODE_QUERY_CANCELED),
 					 errmsg("canceling autovacuum task")));
+		else if (MyProc->terminate)
+			ereport(ERROR,
+					(errcode(ERRCODE_ADMIN_SHUTDOWN),
+					 errmsg("terminating backend due to administrator command")));
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_QUERY_CANCELED),
@@ -3459,6 +3464,9 @@ PostgresMain(int argc, char *argv[], const char *username)
 		/* We don't have a transaction command open anymore */
 		xact_started = false;
 
+		if (MyProc->terminate)
+			die(SIGINT);
+
 		/* Now we can allow interrupts again */
 		RESUME_INTERRUPTS();
 	}
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index f7aaec12f0ef3d8fd11b886c2ce383f27eb6e96a..d5e794abee24386771aecba93f41c98c93873278 100644
--- a/src/backend/utils/adt/misc.c
+++ b/src/backend/utils/adt/misc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.59 2008/04/04 16:57:21 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.60 2008/04/15 13:55:11 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,6 +27,7 @@
 #include "postmaster/syslogger.h"
 #include "storage/fd.h"
 #include "storage/pmsignal.h"
+#include "storage/proc.h"
 #include "storage/procarray.h"
 #include "utils/builtins.h"
 #include "tcop/tcopprot.h"
@@ -89,7 +90,7 @@ current_query(PG_FUNCTION_ARGS)
  * Functions to send signals to other backends.
  */
 static bool
-pg_signal_backend(int pid, int sig)
+pg_signal_check(int pid)
 {
 	if (!superuser())
 		ereport(ERROR,
@@ -106,7 +107,16 @@ pg_signal_backend(int pid, int sig)
 				(errmsg("PID %d is not a PostgreSQL server process", pid)));
 		return false;
 	}
+	else
+		return true;
+}
 
+/*
+ * Functions to send signals to other backends.
+ */
+static bool
+pg_signal_backend(int pid, int sig)
+{
 	/* If we have setsid(), signal the backend's whole process group */
 #ifdef HAVE_SETSID
 	if (kill(-pid, sig))
@@ -125,7 +135,43 @@ pg_signal_backend(int pid, int sig)
 Datum
 pg_cancel_backend(PG_FUNCTION_ARGS)
 {
-	PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGINT));
+	int pid = PG_GETARG_INT32(0);
+	
+	if (pg_signal_check(pid))
+		PG_RETURN_BOOL(pg_signal_backend(pid, SIGINT));
+	else
+		PG_RETURN_BOOL(false);
+}
+
+/*
+ *	To cleanly terminate a backend, we set PGPROC(pid)->terminate
+ *	then send a cancel signal.  We get ProcArrayLock only when
+ *	setting PGPROC->terminate so the function might fail in
+ *	several places, but that is fine because in those cases the
+ *	backend is already gone.
+ */
+Datum
+pg_terminate_backend(PG_FUNCTION_ARGS)
+{
+	int pid = PG_GETARG_INT32(0);
+	volatile PGPROC *term_proc;
+
+	/* Is this the super-user, and can we find the PGPROC entry for the pid? */
+	if (pg_signal_check(pid) && (term_proc = BackendPidGetProc(pid)) != NULL)
+	{
+		LWLockAcquire(ProcArrayLock, LW_EXCLUSIVE);
+		/* Recheck now that we have the ProcArray lock. */
+		if (term_proc->pid == pid)
+		{
+			term_proc->terminate = true;
+			LWLockRelease(ProcArrayLock);
+			PG_RETURN_BOOL(pg_signal_backend(pid, SIGINT));
+		}
+		else
+			LWLockRelease(ProcArrayLock);
+	}
+
+	PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -169,17 +215,6 @@ pg_rotate_logfile(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(true);
 }
 
-#ifdef NOT_USED
-
-/* Disabled in 8.0 due to reliability concerns; FIXME someday */
-Datum
-pg_terminate_backend(PG_FUNCTION_ARGS)
-{
-	PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0), SIGTERM));
-}
-#endif
-
-
 /* Function to find out which databases make use of a tablespace */
 
 typedef struct
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 6eefea9491a283ccd02d2f0cb42f04c08b781f98..0cfe54959dfa47c5391c80a22dffbdb19ee0bdb6 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.489 2008/04/14 17:05:33 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.490 2008/04/15 13:55:11 momjian Exp $
  *
  * NOTES
  *	  The script catalog/genbki.sh reads this file and generates .bki
@@ -3157,6 +3157,8 @@ DESCR("is schema another session's temp schema?");
 
 DATA(insert OID = 2171 ( pg_cancel_backend		PGNSP PGUID 12 1 0 f f t f v 1 16 "23" _null_ _null_ _null_ pg_cancel_backend - _null_ _null_ ));
 DESCR("cancel a server process' current query");
+DATA(insert OID = 2096 ( pg_terminate_backend		PGNSP PGUID 12 1 0 f f t f v 1 16 "23" _null_ _null_ _null_ pg_terminate_backend - _null_ _null_ ));
+DESCR("terminate a server process");
 DATA(insert OID = 2172 ( pg_start_backup		PGNSP PGUID 12 1 0 f f t f v 1 25 "25" _null_ _null_ _null_ pg_start_backup - _null_ _null_ ));
 DESCR("prepare for taking an online backup");
 DATA(insert OID = 2173 ( pg_stop_backup			PGNSP PGUID 12 1 0 f f t f v 0 25 "" _null_ _null_ _null_ pg_stop_backup - _null_ _null_ ));
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 1ce3eb26fc324a49ff144c8af155402ef5e174d5..8e906a910c1e9f2190df91d65b81f257a0ff8010 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.104 2008/01/26 19:55:08 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/storage/proc.h,v 1.105 2008/04/15 13:55:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -91,6 +91,8 @@ struct PGPROC
 
 	bool		inCommit;		/* true if within commit critical section */
 
+	bool		terminate;		/* admin requested termination */
+
 	uint8		vacuumFlags;	/* vacuum-related flags, see above */
 
 	/* Info about LWLock the process is currently waiting for, if any. */
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index c14fcab72e854ef2242cd13673e0542bb0ffa343..629b5b916f2cb1d3d437f91ad43a647459dd0434 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.312 2008/04/04 18:45:36 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.313 2008/04/15 13:55:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -416,6 +416,7 @@ extern Datum nonnullvalue(PG_FUNCTION_ARGS);
 extern Datum current_database(PG_FUNCTION_ARGS);
 extern Datum current_query(PG_FUNCTION_ARGS);
 extern Datum pg_cancel_backend(PG_FUNCTION_ARGS);
+extern Datum pg_terminate_backend(PG_FUNCTION_ARGS);
 extern Datum pg_reload_conf(PG_FUNCTION_ARGS);
 extern Datum pg_tablespace_databases(PG_FUNCTION_ARGS);
 extern Datum pg_rotate_logfile(PG_FUNCTION_ARGS);