Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitaaf0432

Browse files
committed
Add functions to wait for backend termination
This adds a function, pg_wait_for_backend_termination(), and a newtimeout argument to pg_terminate_backend(), which will wait for thebackend to actually terminate (with or without signaling it to do sodepending on which function is called). The default behaviour ofpg_terminate_backend() remains being timeout=0 which does not waiting.For pg_wait_for_backend_termination() the default wait is 5 seconds.Author: Bharath RupireddyReviewed-By: Fujii Masao, David Johnston, Muhammad Usama, Hou Zhijie, Magnus HaganderDiscussion:https://postgr.es/m/CALj2ACUBpunmyhYZw-kXCYs5NM+h6oG_7Df_Tn4mLmmUQifkqA@mail.gmail.com
1 parentfb310f1 commitaaf0432

File tree

7 files changed

+174
-7
lines changed

7 files changed

+174
-7
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24977,7 +24977,7 @@ SELECT collation for ('foo' COLLATE "de_DE");
2497724977
<indexterm>
2497824978
<primary>pg_terminate_backend</primary>
2497924979
</indexterm>
24980-
<function>pg_terminate_backend</function> ( <parameter>pid</parameter> <type>integer</type> )
24980+
<function>pg_terminate_backend</function> ( <parameter>pid</parameter> <type>integer</type>, <parameter>timeout</parameter> <type>bigint</type> <literal>DEFAULT</literal> <literal>0</literal> )
2498124981
<returnvalue>boolean</returnvalue>
2498224982
</para>
2498324983
<para>
@@ -24986,6 +24986,34 @@ SELECT collation for ('foo' COLLATE "de_DE");
2498624986
is a member of the role whose backend is being terminated or the
2498724987
calling role has been granted <literal>pg_signal_backend</literal>,
2498824988
however only superusers can terminate superuser backends.
24989+
</para>
24990+
<para>
24991+
If <parameter>timeout</parameter> is not specified or zero, this
24992+
function returns <literal>true</literal> whether the process actually
24993+
terminates or not, indicating only that the sending of the signal was
24994+
successful. If the <parameter>timeout</parameter> is specified (in
24995+
milliseconds) and greater than zero, the function waits until the
24996+
process is actually terminated or until the given time has passed. If
24997+
the process is terminated, the function
24998+
returns <literal>true</literal>. On timeout a warning is emitted and
24999+
<literal>false</literal> is returned.
25000+
</para></entry>
25001+
</row>
25002+
25003+
<row>
25004+
<entry role="func_table_entry"><para role="func_signature">
25005+
<indexterm>
25006+
<primary>pg_wait_for_backend_termination</primary>
25007+
</indexterm>
25008+
<function>pg_wait_for_backend_termination</function> ( <parameter>pid</parameter> <type>integer</type>, <parameter>timeout</parameter> <type>bigint</type> <literal>DEFAULT</literal> <literal>5000</literal> )
25009+
<returnvalue>boolean</returnvalue>
25010+
</para>
25011+
<para>
25012+
Waits for the backend process with the specified Process ID to
25013+
terminate. If the process terminates before
25014+
the <parameter>timeout</parameter> (in milliseconds)
25015+
expires, <literal>true</literal> is returned. On timeout, a warning
25016+
is emitted and <literal>false</literal> is returned.
2498925017
</para></entry>
2499025018
</row>
2499125019
</tbody>

‎doc/src/sgml/monitoring.sgml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1585,6 +1585,10 @@ postgres 27093 0.0 0.0 30096 2752 ? Ss 11:34 0:00 postgres: ser
15851585
<entry>Waiting for subplan nodes of an <literal>Append</literal> plan
15861586
node to be ready.</entry>
15871587
</row>
1588+
<row>
1589+
<entry><literal>BackendTermination</literal></entry>
1590+
<entry>Waiting for the termination of another backend.</entry>
1591+
</row>
15881592
<row>
15891593
<entry><literal>BackupWaitWalArchive</literal></entry>
15901594
<entry>Waiting for WAL files required for a backup to be successfully

‎src/backend/catalog/system_views.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,16 @@ CREATE OR REPLACE FUNCTION
13471347
RETURNSboolean STRICT VOLATILE LANGUAGE INTERNALAS'pg_promote'
13481348
PARALLEL SAFE;
13491349

1350+
CREATEOR REPLACE FUNCTION
1351+
pg_terminate_backend(pidinteger, timeout int8 DEFAULT0)
1352+
RETURNSboolean STRICT VOLATILE LANGUAGE INTERNALAS'pg_terminate_backend'
1353+
PARALLEL SAFE;
1354+
1355+
CREATEOR REPLACE FUNCTION
1356+
pg_wait_for_backend_termination(pidinteger, timeout int8 DEFAULT5000)
1357+
RETURNSboolean STRICT VOLATILE LANGUAGE INTERNALAS'pg_wait_for_backend_termination'
1358+
PARALLEL SAFE;
1359+
13501360
-- legacy definition for compatibility with 9.3
13511361
CREATEOR REPLACE FUNCTION
13521362
json_populate_record(base anyelement, from_json json, use_json_as_textboolean DEFAULT false)

‎src/backend/storage/ipc/signalfuncs.c

Lines changed: 120 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include"catalog/pg_authid.h"
2020
#include"miscadmin.h"
21+
#include"pgstat.h"
2122
#include"postmaster/syslogger.h"
2223
#include"storage/pmsignal.h"
2324
#include"storage/proc.h"
@@ -126,15 +127,90 @@ pg_cancel_backend(PG_FUNCTION_ARGS)
126127
}
127128

128129
/*
129-
* Signal to terminate a backend process. This is allowed if you are a member
130-
* of the role whose process is being terminated.
130+
* Wait until there is no backend process with the given PID and return true.
131+
* On timeout, a warning is emitted and false is returned.
132+
*/
133+
staticbool
134+
pg_wait_until_termination(intpid,int64timeout)
135+
{
136+
/*
137+
* Wait in steps of waittime milliseconds until this function exits or
138+
* timeout.
139+
*/
140+
int64waittime=100;
141+
/*
142+
* Initially remaining time is the entire timeout specified by the user.
143+
*/
144+
int64remainingtime=timeout;
145+
146+
/*
147+
* Check existence of the backend. If the backend still exists, then wait
148+
* for waittime milliseconds, again check for the existence. Repeat this
149+
* until timeout or an error occurs or a pending interrupt such as query
150+
* cancel gets processed.
151+
*/
152+
do
153+
{
154+
if (remainingtime<waittime)
155+
waittime=remainingtime;
156+
157+
if (kill(pid,0)==-1)
158+
{
159+
if (errno==ESRCH)
160+
return true;
161+
else
162+
ereport(ERROR,
163+
(errcode(ERRCODE_INTERNAL_ERROR),
164+
errmsg("could not check the existence of the backend with PID %d: %m",
165+
pid)));
166+
}
167+
168+
/* Process interrupts, if any, before waiting */
169+
CHECK_FOR_INTERRUPTS();
170+
171+
(void)WaitLatch(MyLatch,
172+
WL_LATCH_SET |WL_TIMEOUT |WL_EXIT_ON_PM_DEATH,
173+
waittime,
174+
WAIT_EVENT_BACKEND_TERMINATION);
175+
176+
ResetLatch(MyLatch);
177+
178+
remainingtime-=waittime;
179+
}while (remainingtime>0);
180+
181+
ereport(WARNING,
182+
(errmsg("backend with PID %d did not terminate within %lld milliseconds",
183+
pid, (long longint)timeout)));
184+
185+
return false;
186+
}
187+
188+
/*
189+
* Signal to terminate a backend process. This is allowed if you are a member
190+
* of the role whose process is being terminated. If timeout input argument is
191+
* 0 (which is default), then this function just signals the backend and
192+
* doesn't wait. Otherwise it waits until given the timeout milliseconds or no
193+
* process has the given PID and returns true. On timeout, a warning is emitted
194+
* and false is returned.
131195
*
132196
* Note that only superusers can signal superuser-owned processes.
133197
*/
134198
Datum
135199
pg_terminate_backend(PG_FUNCTION_ARGS)
136200
{
137-
intr=pg_signal_backend(PG_GETARG_INT32(0),SIGTERM);
201+
intpid;
202+
intr;
203+
inttimeout;
204+
205+
pid=PG_GETARG_INT32(0);
206+
timeout=PG_GETARG_INT64(1);
207+
208+
if (timeout<0)
209+
ereport(ERROR,
210+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
211+
errmsg("\"timeout\" must not be negative")));
212+
213+
r=pg_signal_backend(pid,SIGTERM);
138214

139215
if (r==SIGNAL_BACKEND_NOSUPERUSER)
140216
ereport(ERROR,
@@ -146,7 +222,47 @@ pg_terminate_backend(PG_FUNCTION_ARGS)
146222
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
147223
errmsg("must be a member of the role whose process is being terminated or member of pg_signal_backend")));
148224

149-
PG_RETURN_BOOL(r==SIGNAL_BACKEND_SUCCESS);
225+
/* Wait only on success and if actually requested */
226+
if (r==SIGNAL_BACKEND_SUCCESS&&timeout>0)
227+
PG_RETURN_BOOL(pg_wait_until_termination(pid,timeout));
228+
else
229+
PG_RETURN_BOOL(r==SIGNAL_BACKEND_SUCCESS);
230+
}
231+
232+
/*
233+
* Wait for a backend process with the given PID to exit or until the given
234+
* timeout milliseconds occurs. Returns true if the backend has exited. On
235+
* timeout a warning is emitted and false is returned.
236+
*
237+
* We allow any user to call this function, consistent with any user being
238+
* able to view the pid of the process in pg_stat_activity etc.
239+
*/
240+
Datum
241+
pg_wait_for_backend_termination(PG_FUNCTION_ARGS)
242+
{
243+
intpid;
244+
int64timeout;
245+
PGPROC*proc=NULL;
246+
247+
pid=PG_GETARG_INT32(0);
248+
timeout=PG_GETARG_INT64(1);
249+
250+
if (timeout <=0)
251+
ereport(ERROR,
252+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
253+
errmsg("\"timeout\" must not be negative or zero")));
254+
255+
proc=BackendPidGetProc(pid);
256+
257+
if (proc==NULL)
258+
{
259+
ereport(WARNING,
260+
(errmsg("PID %d is not a PostgreSQL server process",pid)));
261+
262+
PG_RETURN_BOOL(false);
263+
}
264+
265+
PG_RETURN_BOOL(pg_wait_until_termination(pid,timeout));
150266
}
151267

152268
/*

‎src/backend/utils/activity/wait_event.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ pgstat_get_wait_ipc(WaitEventIPC w)
313313
caseWAIT_EVENT_APPEND_READY:
314314
event_name="AppendReady";
315315
break;
316+
caseWAIT_EVENT_BACKEND_TERMINATION:
317+
event_name="BackendTermination";
318+
break;
316319
caseWAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE:
317320
event_name="BackupWaitWalArchive";
318321
break;

‎src/include/catalog/pg_proc.dat

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6190,9 +6190,14 @@
61906190
{ oid => '2171', descr => 'cancel a server process\' current query',
61916191
proname => 'pg_cancel_backend', provolatile => 'v', prorettype => 'bool',
61926192
proargtypes => 'int4', prosrc => 'pg_cancel_backend' },
6193-
{ oid => '2096', descr => 'terminate aserver process',
6193+
{ oid => '2096', descr => 'terminate abackend process and if timeout is specified, wait for its exit or until timeout occurs',
61946194
proname => 'pg_terminate_backend', provolatile => 'v', prorettype => 'bool',
6195-
proargtypes => 'int4', prosrc => 'pg_terminate_backend' },
6195+
proargtypes => 'int4 int8', proargnames => '{pid,timeout}',
6196+
prosrc => 'pg_terminate_backend' },
6197+
{ oid => '2137', descr => 'wait for a backend process exit or timeout occurs',
6198+
proname => 'pg_wait_for_backend_termination', provolatile => 'v', prorettype => 'bool',
6199+
proargtypes => 'int4 int8', proargnames => '{pid,timeout}',
6200+
prosrc => 'pg_wait_for_backend_termination' },
61966201
{ oid => '2172', descr => 'prepare for taking an online backup',
61976202
proname => 'pg_start_backup', provolatile => 'v', proparallel => 'r',
61986203
prorettype => 'pg_lsn', proargtypes => 'text bool bool',

‎src/include/utils/wait_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ typedef enum
8080
typedefenum
8181
{
8282
WAIT_EVENT_APPEND_READY=PG_WAIT_IPC,
83+
WAIT_EVENT_BACKEND_TERMINATION,
8384
WAIT_EVENT_BACKUP_WAIT_WAL_ARCHIVE,
8485
WAIT_EVENT_BGWORKER_SHUTDOWN,
8586
WAIT_EVENT_BGWORKER_STARTUP,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp