88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.59 2008/04/04 16:57:21 momjian Exp $
11+ * $PostgreSQL: pgsql/src/backend/utils/adt/misc.c,v 1.60 2008/04/15 13:55:11 momjian Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
2727#include "postmaster/syslogger.h"
2828#include "storage/fd.h"
2929#include "storage/pmsignal.h"
30+ #include "storage/proc.h"
3031#include "storage/procarray.h"
3132#include "utils/builtins.h"
3233#include "tcop/tcopprot.h"
@@ -89,7 +90,7 @@ current_query(PG_FUNCTION_ARGS)
8990 * Functions to send signals to other backends.
9091 */
9192static bool
92- pg_signal_backend (int pid , int sig )
93+ pg_signal_check (int pid )
9394{
9495if (!superuser ())
9596ereport (ERROR ,
@@ -106,7 +107,16 @@ pg_signal_backend(int pid, int sig)
106107(errmsg ("PID %d is not a PostgreSQL server process" ,pid )));
107108return false;
108109}
110+ else
111+ return true;
112+ }
109113
114+ /*
115+ * Functions to send signals to other backends.
116+ */
117+ static bool
118+ pg_signal_backend (int pid ,int sig )
119+ {
110120/* If we have setsid(), signal the backend's whole process group */
111121#ifdef HAVE_SETSID
112122if (kill (- pid ,sig ))
@@ -125,7 +135,43 @@ pg_signal_backend(int pid, int sig)
125135Datum
126136pg_cancel_backend (PG_FUNCTION_ARGS )
127137{
128- PG_RETURN_BOOL (pg_signal_backend (PG_GETARG_INT32 (0 ),SIGINT ));
138+ int pid = PG_GETARG_INT32 (0 );
139+
140+ if (pg_signal_check (pid ))
141+ PG_RETURN_BOOL (pg_signal_backend (pid ,SIGINT ));
142+ else
143+ PG_RETURN_BOOL (false);
144+ }
145+
146+ /*
147+ *To cleanly terminate a backend, we set PGPROC(pid)->terminate
148+ *then send a cancel signal. We get ProcArrayLock only when
149+ *setting PGPROC->terminate so the function might fail in
150+ *several places, but that is fine because in those cases the
151+ *backend is already gone.
152+ */
153+ Datum
154+ pg_terminate_backend (PG_FUNCTION_ARGS )
155+ {
156+ int pid = PG_GETARG_INT32 (0 );
157+ volatile PGPROC * term_proc ;
158+
159+ /* Is this the super-user, and can we find the PGPROC entry for the pid? */
160+ if (pg_signal_check (pid )&& (term_proc = BackendPidGetProc (pid ))!= NULL )
161+ {
162+ LWLockAcquire (ProcArrayLock ,LW_EXCLUSIVE );
163+ /* Recheck now that we have the ProcArray lock. */
164+ if (term_proc -> pid == pid )
165+ {
166+ term_proc -> terminate = true;
167+ LWLockRelease (ProcArrayLock );
168+ PG_RETURN_BOOL (pg_signal_backend (pid ,SIGINT ));
169+ }
170+ else
171+ LWLockRelease (ProcArrayLock );
172+ }
173+
174+ PG_RETURN_BOOL (false);
129175}
130176
131177Datum
@@ -169,17 +215,6 @@ pg_rotate_logfile(PG_FUNCTION_ARGS)
169215PG_RETURN_BOOL (true);
170216}
171217
172- #ifdef NOT_USED
173-
174- /* Disabled in 8.0 due to reliability concerns; FIXME someday */
175- Datum
176- pg_terminate_backend (PG_FUNCTION_ARGS )
177- {
178- PG_RETURN_INT32 (pg_signal_backend (PG_GETARG_INT32 (0 ),SIGTERM ));
179- }
180- #endif
181-
182-
183218/* Function to find out which databases make use of a tablespace */
184219
185220typedef struct