LCOV - code coverage report
Current view: top level - src/port - pqsignal.c (source / functions) Coverage Total Hit
Test: Code coverage Lines: 86.2 % 29 25
Test Date: 2026-01-26 10:56:24 Functions: 100.0 % 3 3
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 65.4 % 26 17

             Branch data     Line data    Source code
       1                 :             : /*-------------------------------------------------------------------------
       2                 :             :  *
       3                 :             :  * pqsignal.c
       4                 :             :  *        reliable BSD-style signal(2) routine stolen from RWW who stole it
       5                 :             :  *        from Stevens...
       6                 :             :  *
       7                 :             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8                 :             :  * Portions Copyright (c) 1994, Regents of the University of California
       9                 :             :  *
      10                 :             :  *
      11                 :             :  * IDENTIFICATION
      12                 :             :  *        src/port/pqsignal.c
      13                 :             :  *
      14                 :             :  *      This is the signal() implementation from "Advanced Programming in the UNIX
      15                 :             :  *      Environment", with minor changes.  It was originally a replacement needed
      16                 :             :  *      for old SVR4 systems whose signal() behaved as if sa_flags = SA_RESETHAND |
      17                 :             :  *      SA_NODEFER, also known as "unreliable" signals due to races when the
      18                 :             :  *      handler was reset.
      19                 :             :  *
      20                 :             :  *      By now, all known modern Unix systems have a "reliable" signal() call.
      21                 :             :  *      We still don't want to use it though, because it remains
      22                 :             :  *      implementation-defined by both C99 and POSIX whether the handler is reset
      23                 :             :  *      or signals are blocked when the handler runs, and default restart behavior
      24                 :             :  *      is also unspecified.  Therefore we take POSIX's advice and call sigaction()
      25                 :             :  *      so we can provide explicit sa_flags, but wrap it in this more convenient
      26                 :             :  *      traditional interface style.  It also provides a place to set any extra
      27                 :             :  *      flags we want everywhere, such as SA_NOCLDSTOP.
      28                 :             :  *
      29                 :             :  *      Windows, of course, is resolutely in a class by itself.  In the backend,
      30                 :             :  *      this relies on pqsigaction() in src/backend/port/win32/signal.c, which
      31                 :             :  *      provides limited emulation of reliable signals.
      32                 :             :  *
      33                 :             :  *      Frontend programs can use this version of pqsignal() to forward to the
      34                 :             :  *      native Windows signal() call if they wish, but beware that Windows signals
      35                 :             :  *      behave quite differently.  Only the 6 signals required by C are supported.
      36                 :             :  *      SIGINT handlers run in another thread instead of interrupting an existing
      37                 :             :  *      thread, and the others don't interrupt system calls either, so SA_RESTART
      38                 :             :  *      is moot.  All except SIGFPE have SA_RESETHAND semantics, meaning the
      39                 :             :  *      handler is reset to SIG_DFL each time it runs.  The set of things you are
      40                 :             :  *      allowed to do in a handler is also much more restricted than on Unix,
      41                 :             :  *      according to the documentation.
      42                 :             :  *
      43                 :             :  * ------------------------------------------------------------------------
      44                 :             :  */
      45                 :             : 
      46                 :             : #include "c.h"
      47                 :             : 
      48                 :             : #include <signal.h>
      49                 :             : #ifndef FRONTEND
      50                 :             : #include <unistd.h>
      51                 :             : #endif
      52                 :             : 
      53                 :             : #ifndef FRONTEND
      54                 :             : #include "libpq/pqsignal.h"
      55                 :             : #include "miscadmin.h"
      56                 :             : #endif
      57                 :             : 
      58                 :             : #ifdef PG_SIGNAL_COUNT                  /* Windows */
      59                 :             : #define PG_NSIG (PG_SIGNAL_COUNT)
      60                 :             : #elif defined(NSIG)
      61                 :             : #define PG_NSIG (NSIG)
      62                 :             : #else
      63                 :             : #define PG_NSIG (64)                    /* XXX: wild guess */
      64                 :             : #endif
      65                 :             : 
      66                 :             : /* Check a couple of common signals to make sure PG_NSIG is accurate. */
      67                 :             : StaticAssertDecl(SIGUSR2 < PG_NSIG, "SIGUSR2 >= PG_NSIG");
      68                 :             : StaticAssertDecl(SIGHUP < PG_NSIG, "SIGHUP >= PG_NSIG");
      69                 :             : StaticAssertDecl(SIGTERM < PG_NSIG, "SIGTERM >= PG_NSIG");
      70                 :             : StaticAssertDecl(SIGALRM < PG_NSIG, "SIGALRM >= PG_NSIG");
      71                 :             : 
      72                 :             : static volatile pqsigfunc pqsignal_handlers[PG_NSIG];
      73                 :             : 
      74                 :             : /*
      75                 :             :  * Except when called with SIG_IGN or SIG_DFL, pqsignal() sets up this function
      76                 :             :  * as the handler for all signals.  This wrapper handler function checks that
      77                 :             :  * it is called within a process that knew to maintain MyProcPid, and not a
      78                 :             :  * child process forked by system(3), etc.  This check ensures that such child
      79                 :             :  * processes do not modify shared memory, which is often detrimental.  If the
      80                 :             :  * check succeeds, the function originally provided to pqsignal() is called.
      81                 :             :  * Otherwise, the default signal handler is installed and then called.
      82                 :             :  *
      83                 :             :  * This wrapper also handles restoring the value of errno.
      84                 :             :  */
      85                 :             : static void
      86                 :        2633 : wrapper_handler(SIGNAL_ARGS)
      87                 :             : {
      88                 :        2633 :         int                     save_errno = errno;
      89                 :             : 
      90         [ +  - ]:        2633 :         Assert(postgres_signal_arg > 0);
      91         [ +  - ]:        2633 :         Assert(postgres_signal_arg < PG_NSIG);
      92                 :             : 
      93                 :             : #ifndef FRONTEND
      94                 :             : 
      95                 :             :         /*
      96                 :             :          * We expect processes to set MyProcPid before calling pqsignal() or
      97                 :             :          * before accepting signals.
      98                 :             :          */
      99         [ +  - ]:        2633 :         Assert(MyProcPid);
     100   [ +  +  +  - ]:        2633 :         Assert(MyProcPid != PostmasterPid || !IsUnderPostmaster);
     101                 :             : 
     102         [ -  + ]:        2633 :         if (unlikely(MyProcPid != (int) getpid()))
     103                 :             :         {
     104                 :           0 :                 pqsignal(postgres_signal_arg, SIG_DFL);
     105                 :           0 :                 raise(postgres_signal_arg);
     106                 :           0 :                 return;
     107                 :             :         }
     108                 :             : #endif
     109                 :             : 
     110                 :        2633 :         (*pqsignal_handlers[postgres_signal_arg]) (postgres_signal_arg);
     111                 :             : 
     112                 :        2633 :         errno = save_errno;
     113         [ -  + ]:        2633 : }
     114                 :             : 
     115                 :             : /*
     116                 :             :  * Set up a signal handler, with SA_RESTART, for signal "signo"
     117                 :             :  *
     118                 :             :  * Note: the actual name of this function is either pqsignal_fe when
     119                 :             :  * compiled with -DFRONTEND, or pqsignal_be when compiled without that.
     120                 :             :  * This is to avoid a name collision with libpq's legacy-pqsignal.c.
     121                 :             :  */
     122                 :             : void
     123                 :       11410 : pqsignal(int signo, pqsigfunc func)
     124                 :             : {
     125                 :             : #if !(defined(WIN32) && defined(FRONTEND))
     126                 :       11410 :         struct sigaction act;
     127                 :             : #endif
     128                 :             : 
     129         [ +  - ]:       11410 :         Assert(signo > 0);
     130         [ +  - ]:       11410 :         Assert(signo < PG_NSIG);
     131                 :             : 
     132   [ +  +  +  + ]:       11410 :         if (func != SIG_IGN && func != SIG_DFL)
     133                 :             :         {
     134                 :        7407 :                 pqsignal_handlers[signo] = func;        /* assumed atomic */
     135                 :        7407 :                 func = wrapper_handler;
     136                 :        7407 :         }
     137                 :             : 
     138                 :             : #if !(defined(WIN32) && defined(FRONTEND))
     139                 :       11410 :         act.sa_handler = func;
     140                 :       11410 :         sigemptyset(&act.sa_mask);
     141                 :       11410 :         act.sa_flags = SA_RESTART;
     142                 :             : #ifdef SA_NOCLDSTOP
     143         [ +  + ]:       11410 :         if (signo == SIGCHLD)
     144                 :        1076 :                 act.sa_flags |= SA_NOCLDSTOP;
     145                 :             : #endif
     146         [ +  - ]:       11410 :         if (sigaction(signo, &act, NULL) < 0)
     147                 :           0 :                 Assert(false);                  /* probably indicates coding error */
     148                 :             : #else
     149                 :             :         /* Forward to Windows native signal system. */
     150                 :             :         if (signal(signo, func) == SIG_ERR)
     151                 :             :                 Assert(false);                  /* probably indicates coding error */
     152                 :             : #endif
     153                 :       11410 : }
        

Generated by: LCOV version 2.3.2-1