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);