LCOV - differential code coverage report
Current view: top level - src/backend/storage/ipc - signalfuncs.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB
Current: Differential Code Coverage HEAD vs 15 Lines: 53.6 % 69 37 1 20 11 4 22 11 16 25 1
Current Date: 2023-04-08 17:13:01 Functions: 71.4 % 7 5 2 3 1 1 2 3
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (240..) days: 53.6 % 69 37 1 20 11 4 22 11 12 25
Legend: Lines: hit not hit Function coverage date bins:
(240..) days: 41.7 % 12 5 2 3 1 1 2 3

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*-------------------------------------------------------------------------
                                  2                 :  *
                                  3                 :  * signalfuncs.c
                                  4                 :  *    Functions for signaling backends
                                  5                 :  *
                                  6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
                                  7                 :  * Portions Copyright (c) 1994, Regents of the University of California
                                  8                 :  *
                                  9                 :  *
                                 10                 :  * IDENTIFICATION
                                 11                 :  *    src/backend/storage/ipc/signalfuncs.c
                                 12                 :  *
                                 13                 :  *-------------------------------------------------------------------------
                                 14                 :  */
                                 15                 : #include "postgres.h"
                                 16                 : 
                                 17                 : #include <signal.h>
                                 18                 : 
                                 19                 : #include "catalog/pg_authid.h"
                                 20                 : #include "miscadmin.h"
                                 21                 : #include "pgstat.h"
                                 22                 : #include "postmaster/syslogger.h"
                                 23                 : #include "storage/pmsignal.h"
                                 24                 : #include "storage/proc.h"
                                 25                 : #include "storage/procarray.h"
                                 26                 : #include "utils/acl.h"
                                 27                 : #include "utils/builtins.h"
                                 28                 : 
                                 29                 : 
                                 30                 : /*
                                 31                 :  * Send a signal to another backend.
                                 32                 :  *
                                 33                 :  * The signal is delivered if the user is either a superuser or the same
                                 34                 :  * role as the backend being signaled. For "dangerous" signals, an explicit
                                 35                 :  * check for superuser needs to be done prior to calling this function.
                                 36                 :  *
                                 37                 :  * Returns 0 on success, 1 on general failure, 2 on normal permission error
                                 38                 :  * and 3 if the caller needs to be a superuser.
                                 39                 :  *
                                 40                 :  * In the event of a general failure (return code 1), a warning message will
                                 41                 :  * be emitted. For permission errors, doing that is the responsibility of
                                 42                 :  * the caller.
                                 43                 :  */
                                 44                 : #define SIGNAL_BACKEND_SUCCESS 0
                                 45                 : #define SIGNAL_BACKEND_ERROR 1
                                 46                 : #define SIGNAL_BACKEND_NOPERMISSION 2
                                 47                 : #define SIGNAL_BACKEND_NOSUPERUSER 3
                                 48                 : static int
 1648 michael                    49 CBC          35 : pg_signal_backend(int pid, int sig)
                                 50                 : {
                                 51              35 :     PGPROC     *proc = BackendPidGetProc(pid);
                                 52                 : 
                                 53                 :     /*
                                 54                 :      * BackendPidGetProc returns NULL if the pid isn't valid; but by the time
                                 55                 :      * we reach kill(), a process for which we get a valid proc here might
                                 56                 :      * have terminated on its own.  There's no way to acquire a lock on an
                                 57                 :      * arbitrary process to prevent that. But since so far all the callers of
                                 58                 :      * this mechanism involve some request for ending the process anyway, that
                                 59                 :      * it might end on its own first is not a problem.
                                 60                 :      *
                                 61                 :      * Note that proc will also be NULL if the pid refers to an auxiliary
                                 62                 :      * process or the postmaster (neither of which can be signaled via
                                 63                 :      * pg_signal_backend()).
                                 64                 :      */
                                 65              35 :     if (proc == NULL)
                                 66                 :     {
                                 67                 :         /*
                                 68                 :          * This is just a warning so a loop-through-resultset will not abort
                                 69                 :          * if one backend terminated on its own during the run.
                                 70                 :          */
 1648 michael                    71 UBC           0 :         ereport(WARNING,
                                 72                 :                 (errmsg("PID %d is not a PostgreSQL backend process", pid)));
                                 73                 : 
                                 74               0 :         return SIGNAL_BACKEND_ERROR;
                                 75                 :     }
                                 76                 : 
                                 77                 :     /* Only allow superusers to signal superuser-owned backends. */
 1648 michael                    78 CBC          35 :     if (superuser_arg(proc->roleId) && !superuser())
 1648 michael                    79 UBC           0 :         return SIGNAL_BACKEND_NOSUPERUSER;
                                 80                 : 
                                 81                 :     /* Users can signal backends they have role membership in. */
 1648 michael                    82 CBC          35 :     if (!has_privs_of_role(GetUserId(), proc->roleId) &&
  738 sfrost                     83 UBC           0 :         !has_privs_of_role(GetUserId(), ROLE_PG_SIGNAL_BACKEND))
 1648 michael                    84               0 :         return SIGNAL_BACKEND_NOPERMISSION;
                                 85                 : 
                                 86                 :     /*
                                 87                 :      * Can the process we just validated above end, followed by the pid being
                                 88                 :      * recycled for a new process, before reaching here?  Then we'd be trying
                                 89                 :      * to kill the wrong thing.  Seems near impossible when sequential pid
                                 90                 :      * assignment and wraparound is used.  Perhaps it could happen on a system
                                 91                 :      * where pid re-use is randomized.  That race condition possibility seems
                                 92                 :      * too unlikely to worry about.
                                 93                 :      */
                                 94                 : 
                                 95                 :     /* If we have setsid(), signal the backend's whole process group */
                                 96                 : #ifdef HAVE_SETSID
 1648 michael                    97 CBC          35 :     if (kill(-pid, sig))
                                 98                 : #else
                                 99                 :     if (kill(pid, sig))
                                100                 : #endif
                                101                 :     {
                                102                 :         /* Again, just a warning to allow loops */
 1648 michael                   103 UBC           0 :         ereport(WARNING,
                                104                 :                 (errmsg("could not send signal to process %d: %m", pid)));
                                105               0 :         return SIGNAL_BACKEND_ERROR;
                                106                 :     }
 1648 michael                   107 CBC          35 :     return SIGNAL_BACKEND_SUCCESS;
                                108                 : }
                                109                 : 
                                110                 : /*
                                111                 :  * Signal to cancel a backend process.  This is allowed if you are a member of
                                112                 :  * the role whose process is being canceled.
                                113                 :  *
                                114                 :  * Note that only superusers can signal superuser-owned processes.
                                115                 :  */
                                116                 : Datum
                                117              29 : pg_cancel_backend(PG_FUNCTION_ARGS)
                                118                 : {
                                119              29 :     int         r = pg_signal_backend(PG_GETARG_INT32(0), SIGINT);
                                120                 : 
                                121              29 :     if (r == SIGNAL_BACKEND_NOSUPERUSER)
 1648 michael                   122 UBC           0 :         ereport(ERROR,
                                123                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                124                 :                  errmsg("permission denied to cancel query"),
                                125                 :                  errdetail("Only roles with the %s attribute may cancel queries of roles with %s.",
                                126                 :                            "SUPERUSER", "SUPERUSER")));
                                127                 : 
 1648 michael                   128 GIC          29 :     if (r == SIGNAL_BACKEND_NOPERMISSION)
 1648 michael                   129 UIC           0 :         ereport(ERROR,
 1648 michael                   130 ECB             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                131                 :                  errmsg("permission denied to cancel query"),
                                132                 :                  errdetail("Only roles with privileges of the role whose query is being canceled or with privileges of the \"%s\" role may cancel this query.",
                                133                 :                            "pg_signal_backend")));
                                134                 : 
 1648 michael                   135 GIC          29 :     PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
                                136                 : }
                                137                 : 
                                138                 : /*
  731 magnus                    139 ECB             :  * Wait until there is no backend process with the given PID and return true.
                                140                 :  * On timeout, a warning is emitted and false is returned.
                                141                 :  */
                                142                 : static bool
  731 magnus                    143 GIC           2 : pg_wait_until_termination(int pid, int64 timeout)
                                144                 : {
                                145                 :     /*
                                146                 :      * Wait in steps of waittime milliseconds until this function exits or
  731 magnus                    147 ECB             :      * timeout.
                                148                 :      */
  697 tgl                       149 GIC           2 :     int64       waittime = 100;
                                150                 : 
                                151                 :     /*
                                152                 :      * Initially remaining time is the entire timeout specified by the user.
  731 magnus                    153 ECB             :      */
  697 tgl                       154 GIC           2 :     int64       remainingtime = timeout;
                                155                 : 
                                156                 :     /*
                                157                 :      * Check existence of the backend. If the backend still exists, then wait
  731 magnus                    158 ECB             :      * for waittime milliseconds, again check for the existence. Repeat this
                                159                 :      * until timeout or an error occurs or a pending interrupt such as query
                                160                 :      * cancel gets processed.
                                161                 :      */
                                162                 :     do
                                163                 :     {
  731 magnus                    164 GIC           6 :         if (remainingtime < waittime)
  731 magnus                    165 UIC           0 :             waittime = remainingtime;
                                166                 : 
  731 magnus                    167 GIC           6 :         if (kill(pid, 0) == -1)
  731 magnus                    168 ECB             :         {
  731 magnus                    169 GBC           2 :             if (errno == ESRCH)
  731 magnus                    170 GIC           2 :                 return true;
  731 magnus                    171 ECB             :             else
  731 magnus                    172 UIC           0 :                 ereport(ERROR,
  731 magnus                    173 ECB             :                         (errcode(ERRCODE_INTERNAL_ERROR),
                                174                 :                          errmsg("could not check the existence of the backend with PID %d: %m",
                                175                 :                                 pid)));
  731 magnus                    176 EUB             :         }
                                177                 : 
                                178                 :         /* Process interrupts, if any, before waiting */
  731 magnus                    179 GIC           4 :         CHECK_FOR_INTERRUPTS();
                                180                 : 
                                181               4 :         (void) WaitLatch(MyLatch,
                                182                 :                          WL_LATCH_SET | WL_TIMEOUT | WL_EXIT_ON_PM_DEATH,
  731 magnus                    183 ECB             :                          waittime,
                                184                 :                          WAIT_EVENT_BACKEND_TERMINATION);
                                185                 : 
  731 magnus                    186 GIC           4 :         ResetLatch(MyLatch);
                                187                 : 
                                188               4 :         remainingtime -= waittime;
                                189               4 :     } while (remainingtime > 0);
  731 magnus                    190 ECB             : 
  731 magnus                    191 UIC           0 :     ereport(WARNING,
  634 peter                     192 ECB             :             (errmsg_plural("backend with PID %d did not terminate within %lld millisecond",
                                193                 :                            "backend with PID %d did not terminate within %lld milliseconds",
                                194                 :                            timeout,
  634 peter                     195 EUB             :                            pid, (long long int) timeout)));
                                196                 : 
  731 magnus                    197 UIC           0 :     return false;
                                198                 : }
                                199                 : 
                                200                 : /*
  664 noah                      201 EUB             :  * Send a signal to terminate a backend process. This is allowed if you are a
                                202                 :  * member of the role whose process is being terminated. If the timeout input
                                203                 :  * argument is 0, then this function just signals the backend and returns
                                204                 :  * true.  If timeout is nonzero, then it waits until no process has the given
                                205                 :  * PID; if the process ends within the timeout, true is returned, and if the
                                206                 :  * timeout is exceeded, a warning is emitted and false is returned.
                                207                 :  *
                                208                 :  * Note that only superusers can signal superuser-owned processes.
                                209                 :  */
                                210                 : Datum
 1648 michael                   211 GIC           6 : pg_terminate_backend(PG_FUNCTION_ARGS)
                                212                 : {
                                213                 :     int         pid;
                                214                 :     int         r;
  664 noah                      215 ECB             :     int         timeout;        /* milliseconds */
                                216                 : 
  731 magnus                    217 GIC           6 :     pid = PG_GETARG_INT32(0);
                                218               6 :     timeout = PG_GETARG_INT64(1);
                                219                 : 
                                220               6 :     if (timeout < 0)
  731 magnus                    221 LBC           0 :         ereport(ERROR,
  731 magnus                    222 ECB             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                223                 :                  errmsg("\"timeout\" must not be negative")));
                                224                 : 
  731 magnus                    225 GBC           6 :     r = pg_signal_backend(pid, SIGTERM);
                                226                 : 
 1648 michael                   227 GIC           6 :     if (r == SIGNAL_BACKEND_NOSUPERUSER)
 1648 michael                   228 UIC           0 :         ereport(ERROR,
 1648 michael                   229 ECB             :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                230                 :                  errmsg("permission denied to terminate process"),
                                231                 :                  errdetail("Only roles with the %s attribute may terminate processes of roles with %s.",
                                232                 :                            "SUPERUSER", "SUPERUSER")));
                                233                 : 
 1648 michael                   234 GBC           6 :     if (r == SIGNAL_BACKEND_NOPERMISSION)
 1648 michael                   235 UIC           0 :         ereport(ERROR,
                                236                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                237                 :                  errmsg("permission denied to terminate process"),
                                238                 :                  errdetail("Only roles with privileges of the role whose process is being terminated or with privileges of the \"%s\" role may terminate this process.",
                                239                 :                            "pg_signal_backend")));
                                240                 : 
                                241                 :     /* Wait only on success and if actually requested */
  731 magnus                    242 CBC           6 :     if (r == SIGNAL_BACKEND_SUCCESS && timeout > 0)
  731 magnus                    243 GBC           2 :         PG_RETURN_BOOL(pg_wait_until_termination(pid, timeout));
                                244                 :     else
  731 magnus                    245 GIC           4 :         PG_RETURN_BOOL(r == SIGNAL_BACKEND_SUCCESS);
                                246                 : }
                                247                 : 
                                248                 : /*
                                249                 :  * Signal to reload the database configuration
 1648 michael                   250 ECB             :  *
                                251                 :  * Permission checking for this function is managed through the normal
                                252                 :  * GRANT system.
                                253                 :  */
                                254                 : Datum
 1648 michael                   255 GIC          16 : pg_reload_conf(PG_FUNCTION_ARGS)
                                256                 : {
                                257              16 :     if (kill(PostmasterPid, SIGHUP))
                                258                 :     {
 1648 michael                   259 UIC           0 :         ereport(WARNING,
                                260                 :                 (errmsg("failed to send signal to postmaster: %m")));
                                261               0 :         PG_RETURN_BOOL(false);
                                262                 :     }
 1648 michael                   263 ECB             : 
 1648 michael                   264 GIC          16 :     PG_RETURN_BOOL(true);
 1648 michael                   265 ECB             : }
                                266                 : 
 1648 michael                   267 EUB             : 
                                268                 : /*
                                269                 :  * Rotate log file
                                270                 :  *
                                271                 :  * This function is kept to support adminpack 1.0.
 1648 michael                   272 ECB             :  */
                                273                 : Datum
 1648 michael                   274 UIC           0 : pg_rotate_logfile(PG_FUNCTION_ARGS)
                                275                 : {
                                276               0 :     if (!superuser())
                                277               0 :         ereport(ERROR,
                                278                 :                 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                279                 :                  errmsg("must be superuser to rotate log files with adminpack 1.0"),
                                280                 :         /* translator: %s is a SQL function name */
                                281                 :                  errhint("Consider using %s, which is part of core, instead.",
 1165 alvherre                  282 EUB             :                          "pg_logfile_rotate()")));
                                283                 : 
 1648 michael                   284 UBC           0 :     if (!Logging_collector)
 1648 michael                   285 EUB             :     {
 1648 michael                   286 UIC           0 :         ereport(WARNING,
                                287                 :                 (errmsg("rotation not possible because log collection not active")));
                                288               0 :         PG_RETURN_BOOL(false);
                                289                 :     }
                                290                 : 
                                291               0 :     SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE);
 1648 michael                   292 UBC           0 :     PG_RETURN_BOOL(true);
                                293                 : }
 1648 michael                   294 EUB             : 
                                295                 : /*
                                296                 :  * Rotate log file
                                297                 :  *
                                298                 :  * Permission checking for this function is managed through the normal
                                299                 :  * GRANT system.
                                300                 :  */
                                301                 : Datum
 1648 michael                   302 UIC           0 : pg_rotate_logfile_v2(PG_FUNCTION_ARGS)
                                303                 : {
                                304               0 :     if (!Logging_collector)
                                305                 :     {
                                306               0 :         ereport(WARNING,
                                307                 :                 (errmsg("rotation not possible because log collection not active")));
                                308               0 :         PG_RETURN_BOOL(false);
                                309                 :     }
 1648 michael                   310 EUB             : 
 1648 michael                   311 UIC           0 :     SendPostmasterSignal(PMSIGNAL_ROTATE_LOGFILE);
 1648 michael                   312 UBC           0 :     PG_RETURN_BOOL(true);
                                313                 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a