From e8d9d68ca4866c775b5d1170581ac9e1ade3abd8 Mon Sep 17 00:00:00 2001 From: Bruce Momjian Date: Wed, 2 Jun 2004 21:29:29 +0000 Subject: [PATCH] Per previous discussions, here are two functions to send INT and TERM (cancel and terminate) signals to other backends. They permit only INT and TERM, and permits sending only to postgresql backends. Magnus Hagander --- src/backend/storage/ipc/sinval.c | 36 +++++++++++++++++++++++- src/backend/utils/adt/misc.c | 48 +++++++++++++++++++++++++++++++- src/include/catalog/catversion.h | 4 +-- src/include/catalog/pg_proc.h | 7 ++++- src/include/storage/sinval.h | 3 +- src/include/utils/builtins.h | 4 ++- 6 files changed, 95 insertions(+), 7 deletions(-) diff --git a/src/backend/storage/ipc/sinval.c b/src/backend/storage/ipc/sinval.c index 570feab25e..856d0f0a73 100644 --- a/src/backend/storage/ipc/sinval.c +++ b/src/backend/storage/ipc/sinval.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.63 2004/05/23 03:50:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/ipc/sinval.c,v 1.64 2004/06/02 21:29:28 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -463,6 +463,40 @@ TransactionIdIsInProgress(TransactionId xid) return result; } +/* + * IsBackendPid -- is a given pid a running backend + */ +bool +IsBackendPid(int pid) +{ + bool result = false; + SISeg *segP = shmInvalBuffer; + ProcState *stateP = segP->procState; + int index; + + LWLockAcquire(SInvalLock, LW_SHARED); + + for (index = 0; index < segP->lastBackend; index++) + { + SHMEM_OFFSET pOffset = stateP[index].procStruct; + + if (pOffset != INVALID_OFFSET) + { + PGPROC *proc = (PGPROC *) MAKE_PTR(pOffset); + + if (proc->pid == pid) + { + result = true; + break; + } + } + } + + LWLockRelease(SInvalLock); + + return result; +} + /* * GetOldestXmin -- returns oldest transaction that was running * when any current transaction was started. diff --git a/src/backend/utils/adt/misc.c b/src/backend/utils/adt/misc.c index 673b175bbc..8ab6953cb0 100644 --- a/src/backend/utils/adt/misc.c +++ b/src/backend/utils/adt/misc.c @@ -8,16 +8,18 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.33 2004/05/21 05:08:02 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.34 2004/06/02 21:29:29 momjian Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include +#include #include "commands/dbcommands.h" #include "miscadmin.h" +#include "storage/sinval.h" #include "utils/builtins.h" @@ -57,3 +59,47 @@ current_database(PG_FUNCTION_ARGS) namestrcpy(db, get_database_name(MyDatabaseId)); PG_RETURN_NAME(db); } + + +/* + * Functions to terminate a backend or cancel a query running on + * a different backend. + */ + +static int pg_signal_backend(int pid, int sig) +{ + if (!superuser()) + ereport(ERROR, + (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), + (errmsg("only superuser can signal other backends")))); + + if (!IsBackendPid(pid)) + { + /* This is just a warning so a loop-through-resultset will not abort + * if one backend terminated on it's own during the run */ + ereport(WARNING, + (errmsg("pid %i is not a postgresql backend",pid))); + return 0; + } + + if (kill(pid, sig)) + { + /* Again, just a warning to allow loops */ + ereport(WARNING, + (errmsg("failed to send signal to backend %i: %m",pid))); + return 0; + } + return 1; +} + +Datum +pg_terminate_backend(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGTERM)); +} + +Datum +pg_cancel_backend(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT32(pg_signal_backend(PG_GETARG_INT32(0),SIGINT)); +} diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index f0c2f82691..bf6ded488c 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.232 2004/05/26 18:37:33 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.233 2004/06/02 21:29:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200405262 +#define CATALOG_VERSION_NO 200406021 #endif diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index c87eb21556..cb3279747b 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.333 2004/05/26 18:37:33 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.334 2004/06/02 21:29:29 momjian Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -2808,6 +2808,11 @@ DESCR("Statistics: Blocks fetched for database"); DATA(insert OID = 1945 ( pg_stat_get_db_blocks_hit PGNSP PGUID 12 f f t f s 1 20 "26" _null_ pg_stat_get_db_blocks_hit - _null_ )); DESCR("Statistics: Blocks found in cache for database"); +DATA(insert OID = 2171 ( pg_terminate_backend PGNSP PGUID 12 f f t f s 1 23 "23" _null_ pg_terminate_backend - _null_ )); +DESCR("Terminate a backend process"); +DATA(insert OID = 2172 ( pg_cancel_backend PGNSP PGUID 12 f f t f s 1 23 "23" _null_ pg_cancel_backend - _null_ )); +DESCR("Cancel running query on a backend process"); + DATA(insert OID = 1946 ( encode PGNSP PGUID 12 f f t f i 2 25 "17 25" _null_ binary_encode - _null_ )); DESCR("Convert bytea value into some ascii-only text string"); DATA(insert OID = 1947 ( decode PGNSP PGUID 12 f f t f i 2 17 "25 25" _null_ binary_decode - _null_ )); diff --git a/src/include/storage/sinval.h b/src/include/storage/sinval.h index a1c731024c..8476920050 100644 --- a/src/include/storage/sinval.h +++ b/src/include/storage/sinval.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.34 2004/05/23 03:50:45 tgl Exp $ + * $PostgreSQL: pgsql/src/include/storage/sinval.h,v 1.35 2004/06/02 21:29:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -97,6 +97,7 @@ extern void ReceiveSharedInvalidMessages( extern bool DatabaseHasActiveBackends(Oid databaseId, bool ignoreMyself); extern bool TransactionIdIsInProgress(TransactionId xid); +extern bool IsBackendPid(int pid); extern TransactionId GetOldestXmin(bool allDbs); extern int CountActiveBackends(void); extern int CountEmptyBackendSlots(void); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 267ededb13..1fc26e69a1 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.240 2004/05/26 18:35:46 momjian Exp $ + * $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.241 2004/06/02 21:29:29 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -354,6 +354,8 @@ extern Datum float84ge(PG_FUNCTION_ARGS); extern Datum nullvalue(PG_FUNCTION_ARGS); extern Datum nonnullvalue(PG_FUNCTION_ARGS); extern Datum current_database(PG_FUNCTION_ARGS); +extern Datum pg_terminate_backend(PG_FUNCTION_ARGS); +extern Datum pg_cancel_backend(PG_FUNCTION_ARGS); /* not_in.c */ extern Datum int4notin(PG_FUNCTION_ARGS); -- 2.40.0