Bruce Momjian wrote:
> I have an idea for this TODO item:
> 
>       * Allow administrators to safely terminate individual sessions either
>         via an SQL function or SIGTERM
>       
>         Lock table corruption following SIGTERM of an individual backend
>         has been reported in 8.0.  A possible cause was fixed in 8.1, but
>         it is unknown whether other problems exist.  This item mostly
>         requires additional testing rather than of writing any new code.
>       
>         http://archives.postgresql.org/pgsql-hackers/2006-08/msg00174.php
> 
> When we get the termination signal, why can't we just set a global
> boolean, do a query cancel, and in the setjmp() code block check the
> global and exit --- at that stage we know we have released all locks and
> can exit cleanly.

I have implemented this idea with the attached patch.

-- 
  Bruce Momjian  <[EMAIL PROTECTED]>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +
Index: doc/src/sgml/func.sgml
===================================================================
RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v
retrieving revision 1.429
diff -c -c -r1.429 func.sgml
*** doc/src/sgml/func.sgml	10 Apr 2008 13:34:33 -0000	1.429
--- doc/src/sgml/func.sgml	12 Apr 2008 13:48:33 -0000
***************
*** 11849,11854 ****
--- 11849,11857 ----
      <primary>pg_cancel_backend</primary>
     </indexterm>
     <indexterm>
+     <primary>pg_terminate_backend</primary>
+    </indexterm>
+    <indexterm>
      <primary>pg_reload_conf</primary>
     </indexterm>
     <indexterm>
***************
*** 11885,11890 ****
--- 11888,11900 ----
        </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>
          </entry>
         <entry><type>boolean</type></entry>
***************
*** 11909,11915 ****
     <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
      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
--- 11919,11927 ----
     <para>
      <function>pg_cancel_backend</> sends a query cancel
      (<systemitem>SIGINT</>) signal to a backend process identified by
!     process ID.  <function>pg_terminate_backend</> sends a terminate
!     (<systemitem>SIGTERM</>) signal to the specified 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
Index: src/backend/port/ipc_test.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/port/ipc_test.c,v
retrieving revision 1.24
diff -c -c -r1.24 ipc_test.c
*** src/backend/port/ipc_test.c	24 Mar 2008 18:08:47 -0000	1.24
--- src/backend/port/ipc_test.c	12 Apr 2008 13:48:33 -0000
***************
*** 40,45 ****
--- 40,46 ----
  
  volatile bool InterruptPending = false;
  volatile bool QueryCancelPending = false;
+ volatile bool BackendTerminatePending = false;
  volatile bool ProcDiePending = false;
  volatile bool ImmediateInterruptOK = false;
  volatile uint32 InterruptHoldoffCount = 0;
Index: src/backend/postmaster/autovacuum.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/postmaster/autovacuum.c,v
retrieving revision 1.76
diff -c -c -r1.76 autovacuum.c
*** src/backend/postmaster/autovacuum.c	26 Mar 2008 21:10:38 -0000	1.76
--- src/backend/postmaster/autovacuum.c	12 Apr 2008 13:48:33 -0000
***************
*** 1475,1481 ****
  	 * means abort and exit cleanly, and SIGQUIT means abandon ship.
  	 */
  	pqsignal(SIGINT, StatementCancelHandler);
! 	pqsignal(SIGTERM, die);
  	pqsignal(SIGQUIT, quickdie);
  	pqsignal(SIGALRM, handle_sig_alarm);
  
--- 1475,1481 ----
  	 * means abort and exit cleanly, and SIGQUIT means abandon ship.
  	 */
  	pqsignal(SIGINT, StatementCancelHandler);
! 	pqsignal(SIGTERM, BackendTerminateHandler);
  	pqsignal(SIGQUIT, quickdie);
  	pqsignal(SIGALRM, handle_sig_alarm);
  
Index: src/backend/tcop/postgres.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/tcop/postgres.c,v
retrieving revision 1.548
diff -c -c -r1.548 postgres.c
*** src/backend/tcop/postgres.c	2 Apr 2008 18:31:50 -0000	1.548
--- src/backend/tcop/postgres.c	12 Apr 2008 13:48:33 -0000
***************
*** 2541,2547 ****
  		 * waiting for input, however.
  		 */
  		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
! 			CritSectionCount == 0 && !DoingCommandRead)
  		{
  			/* bump holdoff count to make ProcessInterrupts() a no-op */
  			/* until we are done getting ready for it */
--- 2541,2548 ----
  		 * waiting for input, however.
  		 */
  		if (ImmediateInterruptOK && InterruptHoldoffCount == 0 &&
! 			CritSectionCount == 0 &&
! 			(!DoingCommandRead || BackendTerminatePending))
  		{
  			/* bump holdoff count to make ProcessInterrupts() a no-op */
  			/* until we are done getting ready for it */
***************
*** 2557,2562 ****
--- 2558,2575 ----
  	errno = save_errno;
  }
  
+ /*
+  * Backend terminate happens by canceling the current query, then
+  * exiting after the longjump() returns to the main query loop.
+  * This is done so that all resources are properly reset before exit.
+  */
+ void
+ BackendTerminateHandler(SIGNAL_ARGS)
+ {
+ 	BackendTerminatePending = true;
+ 	StatementCancelHandler(postgres_signal_arg);
+ }
+ 
  /* signal handler for floating point exception */
  void
  FloatExceptionHandler(SIGNAL_ARGS)
***************
*** 2621,2626 ****
--- 2634,2643 ----
  			ereport(ERROR,
  					(errcode(ERRCODE_QUERY_CANCELED),
  					 errmsg("canceling autovacuum task")));
+ 		else if (BackendTerminatePending)
+ 				ereport(ERROR,
+ 					(errcode(ERRCODE_QUERY_CANCELED),
+ 					 errmsg("terminating backend due to user request")));
  		else
  			ereport(ERROR,
  					(errcode(ERRCODE_QUERY_CANCELED),
***************
*** 3154,3160 ****
  	 */
  	pqsignal(SIGHUP, SigHupHandler);	/* set flag to read config file */
  	pqsignal(SIGINT, StatementCancelHandler);	/* cancel current query */
! 	pqsignal(SIGTERM, die);		/* cancel current query and exit */
  
  	/*
  	 * In a standalone backend, SIGQUIT can be generated from the keyboard
--- 3171,3177 ----
  	 */
  	pqsignal(SIGHUP, SigHupHandler);	/* set flag to read config file */
  	pqsignal(SIGINT, StatementCancelHandler);	/* cancel current query */
! 	pqsignal(SIGTERM, BackendTerminateHandler);
  
  	/*
  	 * In a standalone backend, SIGQUIT can be generated from the keyboard
***************
*** 3459,3464 ****
--- 3476,3484 ----
  		/* We don't have a transaction command open anymore */
  		xact_started = false;
  
+ 		if (BackendTerminatePending)
+ 			die(SIGTERM);
+ 
  		/* Now we can allow interrupts again */
  		RESUME_INTERRUPTS();
  	}
Index: src/backend/utils/adt/misc.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v
retrieving revision 1.59
diff -c -c -r1.59 misc.c
*** src/backend/utils/adt/misc.c	4 Apr 2008 16:57:21 -0000	1.59
--- src/backend/utils/adt/misc.c	12 Apr 2008 13:48:33 -0000
***************
*** 129,134 ****
--- 129,140 ----
  }
  
  Datum
+ pg_terminate_backend(PG_FUNCTION_ARGS)
+ {
+ 	PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGTERM));
+ }
+ 
+ Datum
  pg_reload_conf(PG_FUNCTION_ARGS)
  {
  	if (!superuser())
Index: src/backend/utils/init/globals.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/init/globals.c,v
retrieving revision 1.105
diff -c -c -r1.105 globals.c
*** src/backend/utils/init/globals.c	17 Feb 2008 02:09:29 -0000	1.105
--- src/backend/utils/init/globals.c	12 Apr 2008 13:48:33 -0000
***************
*** 27,32 ****
--- 27,33 ----
  
  volatile bool InterruptPending = false;
  volatile bool QueryCancelPending = false;
+ volatile bool BackendTerminatePending = false;
  volatile bool ProcDiePending = false;
  volatile bool ImmediateInterruptOK = false;
  volatile uint32 InterruptHoldoffCount = 0;
Index: src/include/miscadmin.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/miscadmin.h,v
retrieving revision 1.201
diff -c -c -r1.201 miscadmin.h
*** src/include/miscadmin.h	20 Feb 2008 22:46:24 -0000	1.201
--- src/include/miscadmin.h	12 Apr 2008 13:48:33 -0000
***************
*** 68,73 ****
--- 68,74 ----
  /* these are marked volatile because they are set by signal handlers: */
  extern PGDLLIMPORT volatile bool InterruptPending;
  extern volatile bool QueryCancelPending;
+ extern volatile bool BackendTerminatePending;
  extern volatile bool ProcDiePending;
  
  /* these are marked volatile because they are examined by signal handlers: */
Index: src/include/catalog/pg_proc.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v
retrieving revision 1.488
diff -c -c -r1.488 pg_proc.h
*** src/include/catalog/pg_proc.h	10 Apr 2008 22:25:25 -0000	1.488
--- src/include/catalog/pg_proc.h	12 Apr 2008 13:48:33 -0000
***************
*** 3157,3162 ****
--- 3157,3164 ----
  
  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_ ));
Index: src/include/tcop/tcopprot.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/tcop/tcopprot.h,v
retrieving revision 1.93
diff -c -c -r1.93 tcopprot.h
*** src/include/tcop/tcopprot.h	10 Mar 2008 12:55:13 -0000	1.93
--- src/include/tcop/tcopprot.h	12 Apr 2008 13:48:33 -0000
***************
*** 60,65 ****
--- 60,66 ----
  extern void quickdie(SIGNAL_ARGS);
  extern void authdie(SIGNAL_ARGS);
  extern void StatementCancelHandler(SIGNAL_ARGS);
+ extern void BackendTerminateHandler(SIGNAL_ARGS);
  extern void FloatExceptionHandler(SIGNAL_ARGS);
  extern void prepare_for_client_read(void);
  extern void client_read_ended(void);
Index: src/include/utils/builtins.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v
retrieving revision 1.312
diff -c -c -r1.312 builtins.h
*** src/include/utils/builtins.h	4 Apr 2008 18:45:36 -0000	1.312
--- src/include/utils/builtins.h	12 Apr 2008 13:48:33 -0000
***************
*** 416,421 ****
--- 416,422 ----
  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);
-- 
Sent via pgsql-patches mailing list (pgsql-patches@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-patches

Reply via email to