Index: doc/src/sgml/func.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/func.sgml,v retrieving revision 1.432 diff -c -c -r1.432 func.sgml *** doc/src/sgml/func.sgml 15 Apr 2008 20:28:46 -0000 1.432 --- doc/src/sgml/func.sgml 16 Apr 2008 03:59:20 -0000 *************** *** 11849,11854 **** --- 11849,11857 ---- pg_cancel_backend + pg_terminate_backend + + pg_reload_conf *************** *** 11885,11890 **** --- 11888,11900 ---- + pg_terminate_backend(pid int) + + boolean + Terminate a backend + + + pg_reload_conf() boolean *************** *** 11907,11915 **** ! pg_cancel_backend sends a query cancel ! (SIGINT) signal to a backend process identified by ! process ID. The process ID of an active backend can be found from the procpid column in the pg_stat_activity view, or by listing the postgres processes on the server with --- 11917,11926 ---- ! pg_cancel_backend and pg_terminate_backend ! send a query cancel (SIGINT) signal to a backend process ! identified by process ID. The ! process ID of an active backend can be found from the procpid column in the pg_stat_activity view, or by listing the postgres processes on the server with Index: doc/src/sgml/runtime.sgml =================================================================== RCS file: /cvsroot/pgsql/doc/src/sgml/runtime.sgml,v retrieving revision 1.413 diff -c -c -r1.413 runtime.sgml *** doc/src/sgml/runtime.sgml 15 Apr 2008 20:28:46 -0000 1.413 --- doc/src/sgml/runtime.sgml 16 Apr 2008 03:59:20 -0000 *************** *** 1372,1377 **** --- 1372,1384 ---- well. + + + To terminate a session while allowing other sessions to continue, use + pg_terminate_backend() () rather than sending a signal + to the child process. + Index: src/backend/access/transam/twophase.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/access/transam/twophase.c,v retrieving revision 1.41 diff -c -c -r1.41 twophase.c *** src/backend/access/transam/twophase.c 25 Mar 2008 22:42:42 -0000 1.41 --- src/backend/access/transam/twophase.c 16 Apr 2008 03:59:20 -0000 *************** *** 283,288 **** --- 283,289 ---- gxact->proc.databaseId = databaseid; gxact->proc.roleId = owner; gxact->proc.inCommit = false; + gxact->proc.terminate = false; gxact->proc.vacuumFlags = 0; gxact->proc.lwWaiting = false; gxact->proc.lwExclusive = false; Index: src/backend/storage/ipc/procarray.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/storage/ipc/procarray.c,v retrieving revision 1.43 diff -c -c -r1.43 procarray.c *** src/backend/storage/ipc/procarray.c 26 Mar 2008 18:48:59 -0000 1.43 --- src/backend/storage/ipc/procarray.c 16 Apr 2008 03:59:20 -0000 *************** *** 935,941 **** * answer to be used ... */ PGPROC * ! BackendPidGetProc(int pid) { PGPROC *result = NULL; ProcArrayStruct *arrayP = procArray; --- 935,941 ---- * answer to be used ... */ PGPROC * ! BackendPidGetProc(int pid, bool want_shlock) { PGPROC *result = NULL; ProcArrayStruct *arrayP = procArray; *************** *** 957,964 **** } } ! LWLockRelease(ProcArrayLock); ! return result; } --- 957,966 ---- } } ! /* Do they want the proc returned with an shared lock? */ ! if (!result || !want_shlock) ! LWLockRelease(ProcArrayLock); ! return result; } *************** *** 1009,1015 **** bool IsBackendPid(int pid) { ! return (BackendPidGetProc(pid) != NULL); } --- 1011,1017 ---- bool IsBackendPid(int pid) { ! return (BackendPidGetProc(pid, false) != NULL); } Index: src/backend/storage/lmgr/proc.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/storage/lmgr/proc.c,v retrieving revision 1.199 diff -c -c -r1.199 proc.c *** src/backend/storage/lmgr/proc.c 26 Jan 2008 19:55:08 -0000 1.199 --- src/backend/storage/lmgr/proc.c 16 Apr 2008 03:59:20 -0000 *************** *** 291,296 **** --- 291,297 ---- MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->inCommit = false; + MyProc->terminate = false; MyProc->vacuumFlags = 0; if (IsAutoVacuumWorkerProcess()) MyProc->vacuumFlags |= PROC_IS_AUTOVACUUM; *************** *** 430,435 **** --- 431,437 ---- MyProc->databaseId = InvalidOid; MyProc->roleId = InvalidOid; MyProc->inCommit = false; + MyProc->terminate = false; /* we don't set the "is autovacuum" flag in the launcher */ MyProc->vacuumFlags = 0; MyProc->lwWaiting = false; *************** *** 1275,1281 **** void ProcSendSignal(int pid) { ! PGPROC *proc = BackendPidGetProc(pid); if (proc != NULL) PGSemaphoreUnlock(&proc->sem); --- 1277,1283 ---- void ProcSendSignal(int pid) { ! PGPROC *proc = BackendPidGetProc(pid, false); if (proc != NULL) PGSemaphoreUnlock(&proc->sem); Index: src/backend/tcop/postgres.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/tcop/postgres.c,v retrieving revision 1.550 diff -c -c -r1.550 postgres.c *** src/backend/tcop/postgres.c 15 Apr 2008 20:28:46 -0000 1.550 --- src/backend/tcop/postgres.c 16 Apr 2008 03:59:23 -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 || MyProc->terminate)) { /* bump holdoff count to make ProcessInterrupts() a no-op */ /* until we are done getting ready for it */ *************** *** 2621,2626 **** --- 2622,2631 ---- 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), *************** *** 3492,3497 **** --- 3497,3505 ---- initStringInfo(&input_message); + if (MyProc->terminate) + proc_exit(0); + /* * (1) If we've reached idle state, tell the frontend we're ready for * a new query. Index: src/backend/utils/adt/misc.c =================================================================== RCS file: /cvsroot/pgsql/src/backend/utils/adt/misc.c,v retrieving revision 1.61 diff -c -c -r1.61 misc.c *** src/backend/utils/adt/misc.c 15 Apr 2008 20:28:46 -0000 1.61 --- src/backend/utils/adt/misc.c 16 Apr 2008 03:59:23 -0000 *************** *** 27,32 **** --- 27,33 ---- #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,95 **** * Functions to send signals to other backends. */ static bool ! pg_signal_backend(int pid, int sig) { if (!superuser()) ereport(ERROR, --- 90,96 ---- * Functions to send signals to other backends. */ static bool ! pg_signal_check(int pid) { if (!superuser()) ereport(ERROR, *************** *** 106,112 **** --- 107,122 ---- (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,131 **** Datum pg_cancel_backend(PG_FUNCTION_ARGS) { ! PG_RETURN_BOOL(pg_signal_backend(PG_GETARG_INT32(0), SIGINT)); } Datum --- 135,168 ---- Datum pg_cancel_backend(PG_FUNCTION_ARGS) { ! 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. SIGTERM isn't 100% safe for ! * cases where other backend will continue to run. ! */ ! 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, true)) != NULL) ! { ! term_proc->terminate = true; ! LWLockRelease(ProcArrayLock); ! PG_RETURN_BOOL(pg_signal_backend(pid, SIGINT)); ! } ! ! PG_RETURN_BOOL(false); } Datum *************** *** 169,185 **** 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 --- 206,211 ---- Index: src/include/catalog/pg_proc.h =================================================================== RCS file: /cvsroot/pgsql/src/include/catalog/pg_proc.h,v retrieving revision 1.491 diff -c -c -r1.491 pg_proc.h *** src/include/catalog/pg_proc.h 15 Apr 2008 20:28:46 -0000 1.491 --- src/include/catalog/pg_proc.h 16 Apr 2008 03:59:23 -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/storage/proc.h =================================================================== RCS file: /cvsroot/pgsql/src/include/storage/proc.h,v retrieving revision 1.106 diff -c -c -r1.106 proc.h *** src/include/storage/proc.h 15 Apr 2008 20:28:47 -0000 1.106 --- src/include/storage/proc.h 16 Apr 2008 03:59:25 -0000 *************** *** 91,96 **** --- 91,98 ---- 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. */ Index: src/include/storage/procarray.h =================================================================== RCS file: /cvsroot/pgsql/src/include/storage/procarray.h,v retrieving revision 1.21 diff -c -c -r1.21 procarray.h *** src/include/storage/procarray.h 26 Mar 2008 16:20:48 -0000 1.21 --- src/include/storage/procarray.h 16 Apr 2008 03:59:25 -0000 *************** *** 35,41 **** extern int GetTransactionsInCommit(TransactionId **xids_p); extern bool HaveTransactionsInCommit(TransactionId *xids, int nxids); ! extern PGPROC *BackendPidGetProc(int pid); extern int BackendXidGetPid(TransactionId xid); extern bool IsBackendPid(int pid); --- 35,41 ---- extern int GetTransactionsInCommit(TransactionId **xids_p); extern bool HaveTransactionsInCommit(TransactionId *xids, int nxids); ! extern PGPROC *BackendPidGetProc(int pid, bool shlock); extern int BackendXidGetPid(TransactionId xid); extern bool IsBackendPid(int pid); Index: src/include/utils/builtins.h =================================================================== RCS file: /cvsroot/pgsql/src/include/utils/builtins.h,v retrieving revision 1.314 diff -c -c -r1.314 builtins.h *** src/include/utils/builtins.h 15 Apr 2008 20:28:47 -0000 1.314 --- src/include/utils/builtins.h 16 Apr 2008 03:59:25 -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);