PostgreSQL Source Code  git master
signalfuncs.c File Reference
#include "postgres.h"
#include <signal.h>
#include "catalog/pg_authid.h"
#include "miscadmin.h"
#include "pgstat.h"
#include "postmaster/syslogger.h"
#include "storage/pmsignal.h"
#include "storage/proc.h"
#include "storage/procarray.h"
#include "utils/acl.h"
#include "utils/fmgrprotos.h"
Include dependency graph for signalfuncs.c:

Go to the source code of this file.

Macros

#define SIGNAL_BACKEND_SUCCESS   0
 
#define SIGNAL_BACKEND_ERROR   1
 
#define SIGNAL_BACKEND_NOPERMISSION   2
 
#define SIGNAL_BACKEND_NOSUPERUSER   3
 
#define SIGNAL_BACKEND_NOAUTOVAC   4
 

Functions

static int pg_signal_backend (int pid, int sig)
 
Datum pg_cancel_backend (PG_FUNCTION_ARGS)
 
static bool pg_wait_until_termination (int pid, int64 timeout)
 
Datum pg_terminate_backend (PG_FUNCTION_ARGS)
 
Datum pg_reload_conf (PG_FUNCTION_ARGS)
 
Datum pg_rotate_logfile (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ SIGNAL_BACKEND_ERROR

#define SIGNAL_BACKEND_ERROR   1

Definition at line 46 of file signalfuncs.c.

◆ SIGNAL_BACKEND_NOAUTOVAC

#define SIGNAL_BACKEND_NOAUTOVAC   4

Definition at line 49 of file signalfuncs.c.

◆ SIGNAL_BACKEND_NOPERMISSION

#define SIGNAL_BACKEND_NOPERMISSION   2

Definition at line 47 of file signalfuncs.c.

◆ SIGNAL_BACKEND_NOSUPERUSER

#define SIGNAL_BACKEND_NOSUPERUSER   3

Definition at line 48 of file signalfuncs.c.

◆ SIGNAL_BACKEND_SUCCESS

#define SIGNAL_BACKEND_SUCCESS   0

Definition at line 45 of file signalfuncs.c.

Function Documentation

◆ pg_cancel_backend()

Datum pg_cancel_backend ( PG_FUNCTION_ARGS  )

Definition at line 136 of file signalfuncs.c.

137 {
138  int r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);
139 
141  ereport(ERROR,
142  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
143  errmsg("permission denied to cancel query"),
144  errdetail("Only roles with the %s attribute may cancel queries of roles with the %s attribute.",
145  "SUPERUSER", "SUPERUSER")));
146 
147  if (r == SIGNAL_BACKEND_NOAUTOVAC)
148  ereport(ERROR,
149  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
150  errmsg("permission denied to cancel query"),
151  errdetail("Only roles with privileges of the \"%s\" role may cancel autovacuum workers.",
152  "pg_signal_autovacuum_worker")));
153 
155  ereport(ERROR,
156  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
157  errmsg("permission denied to cancel query"),
158  errdetail("Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query.",
159  "pg_signal_backend")));
160 
162 }
int errdetail(const char *fmt,...)
Definition: elog.c:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_GETARG_INT32(n)
Definition: fmgr.h:269
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static int pg_signal_backend(int pid, int sig)
Definition: signalfuncs.c:51
#define SIGNAL_BACKEND_SUCCESS
Definition: signalfuncs.c:45
#define SIGNAL_BACKEND_NOPERMISSION
Definition: signalfuncs.c:47
#define SIGNAL_BACKEND_NOSUPERUSER
Definition: signalfuncs.c:48
#define SIGNAL_BACKEND_NOAUTOVAC
Definition: signalfuncs.c:49

References ereport, errcode(), errdetail(), errmsg(), ERROR, PG_GETARG_INT32, PG_RETURN_BOOL, pg_signal_backend(), SIGNAL_BACKEND_NOAUTOVAC, SIGNAL_BACKEND_NOPERMISSION, SIGNAL_BACKEND_NOSUPERUSER, and SIGNAL_BACKEND_SUCCESS.

◆ pg_reload_conf()

Datum pg_reload_conf ( PG_FUNCTION_ARGS  )

Definition at line 288 of file signalfuncs.c.

289 {
290  if (kill(PostmasterPid, SIGHUP))
291  {
293  (errmsg("failed to send signal to postmaster: %m")));
294  PG_RETURN_BOOL(false);
295  }
296 
297  PG_RETURN_BOOL(true);
298 }
#define WARNING
Definition: elog.h:36
pid_t PostmasterPid
Definition: globals.c:105
#define SIGHUP
Definition: win32_port.h:168
#define kill(pid, sig)
Definition: win32_port.h:503

References ereport, errmsg(), kill, PG_RETURN_BOOL, PostmasterPid, SIGHUP, and WARNING.

◆ pg_rotate_logfile()

Datum pg_rotate_logfile ( PG_FUNCTION_ARGS  )

Definition at line 308 of file signalfuncs.c.

309 {
310  if (!Logging_collector)
311  {
313  (errmsg("rotation not possible because log collection not active")));
314  PG_RETURN_BOOL(false);
315  }
316 
318  PG_RETURN_BOOL(true);
319 }
void SendPostmasterSignal(PMSignalReason reason)
Definition: pmsignal.c:181
@ PMSIGNAL_ROTATE_LOGFILE
Definition: pmsignal.h:37
bool Logging_collector
Definition: syslogger.c:70

References ereport, errmsg(), Logging_collector, PG_RETURN_BOOL, PMSIGNAL_ROTATE_LOGFILE, SendPostmasterSignal(), and WARNING.

◆ pg_signal_backend()

static int pg_signal_backend ( int  pid,
int  sig 
)
static

Definition at line 51 of file signalfuncs.c.

52 {
53  PGPROC *proc = BackendPidGetProc(pid);
54 
55  /*
56  * BackendPidGetProc returns NULL if the pid isn't valid; but by the time
57  * we reach kill(), a process for which we get a valid proc here might
58  * have terminated on its own. There's no way to acquire a lock on an
59  * arbitrary process to prevent that. But since so far all the callers of
60  * this mechanism involve some request for ending the process anyway, that
61  * it might end on its own first is not a problem.
62  *
63  * Note that proc will also be NULL if the pid refers to an auxiliary
64  * process or the postmaster (neither of which can be signaled via
65  * pg_signal_backend()).
66  */
67  if (proc == NULL)
68  {
69  /*
70  * This is just a warning so a loop-through-resultset will not abort
71  * if one backend terminated on its own during the run.
72  */
74  (errmsg("PID %d is not a PostgreSQL backend process", pid)));
75 
76  return SIGNAL_BACKEND_ERROR;
77  }
78 
79  /*
80  * Only allow superusers to signal superuser-owned backends. Any process
81  * not advertising a role might have the importance of a superuser-owned
82  * backend, so treat it that way. As an exception, we allow roles with
83  * privileges of pg_signal_autovacuum_worker to signal autovacuum workers
84  * (which do not advertise a role).
85  *
86  * Otherwise, users can signal backends for roles they have privileges of.
87  */
88  if (!OidIsValid(proc->roleId) || superuser_arg(proc->roleId))
89  {
90  ProcNumber procNumber = GetNumberFromPGProc(proc);
91  PgBackendStatus *procStatus = pgstat_get_beentry_by_proc_number(procNumber);
92 
93  if (procStatus && procStatus->st_backendType == B_AUTOVAC_WORKER)
94  {
95  if (!has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_AUTOVACUUM_WORKER))
97  }
98  else if (!superuser())
100  }
101  else if (!has_privs_of_role(GetUserId(), proc->roleId) &&
102  !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
104 
105  /*
106  * Can the process we just validated above end, followed by the pid being
107  * recycled for a new process, before reaching here? Then we'd be trying
108  * to kill the wrong thing. Seems near impossible when sequential pid
109  * assignment and wraparound is used. Perhaps it could happen on a system
110  * where pid re-use is randomized. That race condition possibility seems
111  * too unlikely to worry about.
112  */
113 
114  /* If we have setsid(), signal the backend's whole process group */
115 #ifdef HAVE_SETSID
116  if (kill(-pid, sig))
117 #else
118  if (kill(pid, sig))
119 #endif
120  {
121  /* Again, just a warning to allow loops */
123  (errmsg("could not send signal to process %d: %m", pid)));
124  return SIGNAL_BACKEND_ERROR;
125  }
126  return SIGNAL_BACKEND_SUCCESS;
127 }
bool has_privs_of_role(Oid member, Oid role)
Definition: acl.c:5268
PgBackendStatus * pgstat_get_beentry_by_proc_number(ProcNumber procNumber)
#define OidIsValid(objectId)
Definition: c.h:778
@ B_AUTOVAC_WORKER
Definition: miscadmin.h:337
Oid GetUserId(void)
Definition: miscinit.c:514
static int sig
Definition: pg_ctl.c:80
#define GetNumberFromPGProc(proc)
Definition: proc.h:433
PGPROC * BackendPidGetProc(int pid)
Definition: procarray.c:3200
int ProcNumber
Definition: procnumber.h:24
#define SIGNAL_BACKEND_ERROR
Definition: signalfuncs.c:46
Definition: proc.h:162
Oid roleId
Definition: proc.h:208
BackendType st_backendType
bool superuser_arg(Oid roleid)
Definition: superuser.c:56
bool superuser(void)
Definition: superuser.c:46

References B_AUTOVAC_WORKER, BackendPidGetProc(), ereport, errmsg(), GetNumberFromPGProc, GetUserId(), has_privs_of_role(), kill, OidIsValid, pgstat_get_beentry_by_proc_number(), PGPROC::roleId, sig, SIGNAL_BACKEND_ERROR, SIGNAL_BACKEND_NOAUTOVAC, SIGNAL_BACKEND_NOPERMISSION, SIGNAL_BACKEND_NOSUPERUSER, SIGNAL_BACKEND_SUCCESS, PgBackendStatus::st_backendType, superuser(), superuser_arg(), and WARNING.

Referenced by pg_cancel_backend(), and pg_terminate_backend().

◆ pg_terminate_backend()

Datum pg_terminate_backend ( PG_FUNCTION_ARGS  )

Definition at line 237 of file signalfuncs.c.

238 {
239  int pid;
240  int r;
241  int timeout; /* milliseconds */
242 
243  pid = PG_GETARG_INT32(0);
244  timeout = PG_GETARG_INT64(1);
245 
246  if (timeout < 0)
247  ereport(ERROR,
248  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
249  errmsg("\"timeout\" must not be negative")));
250 
251  r = pg_signal_backend(pid, SIGTERM);
252 
254  ereport(ERROR,
255  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
256  errmsg("permission denied to terminate process"),
257  errdetail("Only roles with the %s attribute may terminate processes of roles with the %s attribute.",
258  "SUPERUSER", "SUPERUSER")));
259 
260  if (r == SIGNAL_BACKEND_NOAUTOVAC)
261  ereport(ERROR,
262  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
263  errmsg("permission denied to terminate process"),
264  errdetail("Only roles with privileges of the \"%s\" role may terminate autovacuum workers.",
265  "pg_signal_autovacuum_worker")));
266 
268  ereport(ERROR,
269  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
270  errmsg("permission denied to terminate process"),
271  errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
272  "pg_signal_backend")));
273 
274  /* Wait only on success and if actually requested */
275  if (r == SIGNAL_BACKEND_SUCCESS && timeout > 0)
277  else
279 }
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
static bool pg_wait_until_termination(int pid, int64 timeout)
Definition: signalfuncs.c:169

References ereport, errcode(), errdetail(), errmsg(), ERROR, PG_GETARG_INT32, PG_GETARG_INT64, PG_RETURN_BOOL, pg_signal_backend(), pg_wait_until_termination(), SIGNAL_BACKEND_NOAUTOVAC, SIGNAL_BACKEND_NOPERMISSION, SIGNAL_BACKEND_NOSUPERUSER, and SIGNAL_BACKEND_SUCCESS.

◆ pg_wait_until_termination()

static bool pg_wait_until_termination ( int  pid,
int64  timeout 
)
static

Definition at line 169 of file signalfuncs.c.

170 {
171  /*
172  * Wait in steps of waittime milliseconds until this function exits or
173  * timeout.
174  */
175  int64 waittime = 100;
176 
177  /*
178  * Initially remaining time is the entire timeout specified by the user.
179  */
180  int64 remainingtime = timeout;
181 
182  /*
183  * Check existence of the backend. If the backend still exists, then wait
184  * for waittime milliseconds, again check for the existence. Repeat this
185  * until timeout or an error occurs or a pending interrupt such as query
186  * cancel gets processed.
187  */
188  do
189  {
190  if (remainingtime < waittime)
191  waittime = remainingtime;
192 
193  if (kill(pid, 0) == -1)
194  {
195  if (errno == ESRCH)
196  return true;
197  else
198  ereport(ERROR,
199  (errcode(ERRCODE_INTERNAL_ERROR),
200  errmsg("could not check the existence of the backend with PID %d: %m",
201  pid)));
202  }
203 
204  /* Process interrupts, if any, before waiting */
206 
207  (void) WaitLatch(MyLatch,
209  waittime,
210  WAIT_EVENT_BACKEND_TERMINATION);
211 
213 
214  remainingtime -= waittime;
215  } while (remainingtime > 0);
216 
218  (errmsg_plural("backend with PID %d did not terminate within %lld millisecond",
219  "backend with PID %d did not terminate within %lld milliseconds",
220  timeout,
221  pid, (long long int) timeout)));
222 
223  return false;
224 }
int errmsg_plural(const char *fmt_singular, const char *fmt_plural, unsigned long n,...)
Definition: elog.c:1180
struct Latch * MyLatch
Definition: globals.c:62
void ResetLatch(Latch *latch)
Definition: latch.c:724
int WaitLatch(Latch *latch, int wakeEvents, long timeout, uint32 wait_event_info)
Definition: latch.c:517
#define WL_TIMEOUT
Definition: latch.h:130
#define WL_EXIT_ON_PM_DEATH
Definition: latch.h:132
#define WL_LATCH_SET
Definition: latch.h:127
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122

References CHECK_FOR_INTERRUPTS, ereport, errcode(), errmsg(), errmsg_plural(), ERROR, kill, MyLatch, ResetLatch(), WaitLatch(), WARNING, WL_EXIT_ON_PM_DEATH, WL_LATCH_SET, and WL_TIMEOUT.

Referenced by pg_terminate_backend().