diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index e7f7fe0..f145c3f 100644
*** a/doc/src/sgml/func.sgml
--- b/doc/src/sgml/func.sgml
*************** SELECT set_config('log_statement_stats',
*** 14244,14251 ****
     <para>
      The functions shown in <xref
      linkend="functions-admin-signal-table"> send control signals to
!     other server processes.  Use of these functions is restricted
!     to superusers.
     </para>
  
     <table id="functions-admin-signal-table">
--- 14244,14251 ----
     <para>
      The functions shown in <xref
      linkend="functions-admin-signal-table"> send control signals to
!     other server processes.  Use of these functions is usually restricted
!     to superusers, with noted exceptions.
     </para>
  
     <table id="functions-admin-signal-table">
*************** SELECT set_config('log_statement_stats',
*** 14262,14268 ****
          <literal><function>pg_cancel_backend(<parameter>pid</parameter> <type>int</>)</function></literal>
          </entry>
         <entry><type>boolean</type></entry>
!        <entry>Cancel a backend's current query</entry>
        </row>
        <row>
         <entry>
--- 14262,14271 ----
          <literal><function>pg_cancel_backend(<parameter>pid</parameter> <type>int</>)</function></literal>
          </entry>
         <entry><type>boolean</type></entry>
!        <entry>Cancel a backend's current query.  You can execute this against
!         another backend that has exactly the same role as the user calling the
!         function.  In all other cases, you must be a superuser.
!         </entry>
        </row>
        <row>
         <entry>
*************** SELECT set_config('log_statement_stats',
*** 14304,14309 ****
--- 14307,14316 ----
      <command>postgres</command> processes on the server (using
      <application>ps</> on Unix or the <application>Task
      Manager</> on <productname>Windows</>).
+     For the more permissive <function>pg_cancel_backend</>, the role of an
+     active backend can be found from
+     the <structfield>usename</structfield> column of the
+     <structname>pg_stat_activity</structname> view.
     </para>
  
     <para>
diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c
index 7a2e0c8..b052149 100644
*** a/src/backend/utils/adt/misc.c
--- b/src/backend/utils/adt/misc.c
***************
*** 30,35 ****
--- 30,36 ----
  #include "postmaster/syslogger.h"
  #include "storage/fd.h"
  #include "storage/pmsignal.h"
+ #include "storage/proc.h"
  #include "storage/procarray.h"
  #include "tcop/tcopprot.h"
  #include "utils/builtins.h"
*************** current_query(PG_FUNCTION_ARGS)
*** 71,84 ****
  
  /*
   * Functions to send signals to other backends.
   */
  static bool
  pg_signal_backend(int pid, int sig)
  {
! 	if (!superuser())
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! 			(errmsg("must be superuser to signal other server processes"))));
  
  	if (!IsBackendPid(pid))
  	{
--- 72,115 ----
  
  /*
   * Functions to send signals to other backends.
+  * 
+  * When calling pg_signal_backend, non-superusers are allowed to send signals
+  * to other backends if they are running as the same role.  Make sure you're
+  * comfortable with that before using it for other types of signaling.  If not,
+  * add your own checks first, as pg_terminate_backend does here.
   */
  static bool
  pg_signal_backend(int pid, int sig)
  {
! 	PGPROC	*proc;
! 	bool	allowed = false;
! 
! 	if (superuser())
! 		allowed = true;
! 	else
! 	{
! 		/*
! 		 * Check for matching roles if we've already failed the superuser test.
! 		 *
! 		 * Trust that BackendPidGetProc will return NULL if the pid isn't valid,
! 		 * even though the check for whether it's a backend process is below.
! 		 * The IsBackendPid check can't be relied on as definitive even if it
! 		 * was first.  The process might end between successive checks
! 		 * regardless of their order, and we don't want to acquire a lock just
! 		 * just to eliminate that possibility.  Since the signal being passed
! 		 * might be a request for cancellation, this is not necessarily even a
! 		 * problem.
! 		 */
! 		proc = BackendPidGetProc(pid);
! 
! 		if ((proc != NULL) && (proc->roleId == GetUserId()))
! 			allowed = true;
! 	}
! 
! 	if (!allowed)
  		ereport(ERROR,
  				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
! 			(errmsg("must be superuser or have the same role to signal other server processes"))));
  
  	if (!IsBackendPid(pid))
  	{
*************** pg_cancel_backend(PG_FUNCTION_ARGS)
*** 115,120 ****
--- 146,161 ----
  Datum
  pg_terminate_backend(PG_FUNCTION_ARGS)
  {
+ 	/*
+ 	 * Since the permissions check for signaling isn't as strict as for
+ 	 * termination, run the superuser only one here and suggest alternatives.
+ 	 */
+ 	if (!superuser())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 				 errmsg("must be superuser to terminate other server processes"),
+ 				 errhint("you can use pg_cancel_backend() on your own processes")));
+ 
  	PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGTERM));
  }
  
