8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
27
27
#include "postmaster/syslogger.h"
28
28
#include "storage/fd.h"
29
29
#include "storage/pmsignal.h"
30
+ #include "storage/proc.h"
30
31
#include "storage/procarray.h"
31
32
#include "utils/builtins.h"
32
33
#include "tcop/tcopprot.h"
@@ -89,7 +90,7 @@ current_query(PG_FUNCTION_ARGS)
89
90
* Functions to send signals to other backends.
90
91
*/
91
92
static bool
92
- pg_signal_backend (int pid , int sig )
93
+ pg_signal_check (int pid )
93
94
{
94
95
if (!superuser ())
95
96
ereport (ERROR ,
@@ -106,7 +107,16 @@ pg_signal_backend(int pid, int sig)
106
107
(errmsg ("PID %d is not a PostgreSQL server process" , pid )));
107
108
return false;
108
109
}
110
+ else
111
+ return true;
112
+ }
109
113
114
+ /*
115
+ * Functions to send signals to other backends.
116
+ */
117
+ static bool
118
+ pg_signal_backend (int pid , int sig )
119
+ {
110
120
/* If we have setsid(), signal the backend's whole process group */
111
121
#ifdef HAVE_SETSID
112
122
if (kill (- pid , sig ))
@@ -125,7 +135,43 @@ pg_signal_backend(int pid, int sig)
125
135
Datum
126
136
pg_cancel_backend (PG_FUNCTION_ARGS )
127
137
{
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);
129
175
}
130
176
131
177
Datum
@@ -169,17 +215,6 @@ pg_rotate_logfile(PG_FUNCTION_ARGS)
169
215
PG_RETURN_BOOL (true);
170
216
}
171
217
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
-
183
218
/* Function to find out which databases make use of a tablespace */
184
219
185
220
typedef struct
0 commit comments