LCOV - differential code coverage report
Current view: top level - src/interfaces/libpq - fe-secure.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 58.4 % 113 66 3 1 13 30 3 40 2 21 12 43 2 1
Current Date: 2023-04-08 15:15:32 Functions: 66.7 % 12 8 2 2 8 2 8
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * fe-secure.c
       4                 :  *    functions related to setting up a secure connection to the backend.
       5                 :  *    Secure connections are expected to provide confidentiality,
       6                 :  *    message integrity and endpoint authentication.
       7                 :  *
       8                 :  *
       9                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
      10                 :  * Portions Copyright (c) 1994, Regents of the University of California
      11                 :  *
      12                 :  *
      13                 :  * IDENTIFICATION
      14                 :  *    src/interfaces/libpq/fe-secure.c
      15                 :  *
      16                 :  *-------------------------------------------------------------------------
      17                 :  */
      18                 : 
      19                 : #include "postgres_fe.h"
      20                 : 
      21                 : #include <signal.h>
      22                 : #include <fcntl.h>
      23                 : #include <ctype.h>
      24                 : 
      25                 : #ifdef WIN32
      26                 : #include "win32.h"
      27                 : #else
      28                 : #include <sys/socket.h>
      29                 : #include <unistd.h>
      30                 : #include <netdb.h>
      31                 : #include <netinet/in.h>
      32                 : #include <netinet/tcp.h>
      33                 : #include <arpa/inet.h>
      34                 : #endif
      35                 : 
      36                 : #include <sys/stat.h>
      37                 : 
      38                 : #ifdef ENABLE_THREAD_SAFETY
      39                 : #ifdef WIN32
      40                 : #include "pthread-win32.h"
      41                 : #else
      42                 : #include <pthread.h>
      43                 : #endif
      44                 : #endif
      45                 : 
      46                 : #include "fe-auth.h"
      47                 : #include "libpq-fe.h"
      48                 : #include "libpq-int.h"
      49                 : 
      50                 : /*
      51                 :  * Macros to handle disabling and then restoring the state of SIGPIPE handling.
      52                 :  * On Windows, these are all no-ops since there's no SIGPIPEs.
      53                 :  */
      54                 : 
      55                 : #ifndef WIN32
      56                 : 
      57                 : #define SIGPIPE_MASKED(conn)    ((conn)->sigpipe_so || (conn)->sigpipe_flag)
      58                 : 
      59                 : #ifdef ENABLE_THREAD_SAFETY
      60                 : 
      61                 : struct sigpipe_info
      62                 : {
      63                 :     sigset_t    oldsigmask;
      64                 :     bool        sigpipe_pending;
      65                 :     bool        got_epipe;
      66                 : };
      67                 : 
      68                 : #define DECLARE_SIGPIPE_INFO(spinfo) struct sigpipe_info spinfo
      69                 : 
      70                 : #define DISABLE_SIGPIPE(conn, spinfo, failaction) \
      71                 :     do { \
      72                 :         (spinfo).got_epipe = false; \
      73                 :         if (!SIGPIPE_MASKED(conn)) \
      74                 :         { \
      75                 :             if (pq_block_sigpipe(&(spinfo).oldsigmask, \
      76                 :                                  &(spinfo).sigpipe_pending) < 0) \
      77                 :                 failaction; \
      78                 :         } \
      79                 :     } while (0)
      80                 : 
      81                 : #define REMEMBER_EPIPE(spinfo, cond) \
      82                 :     do { \
      83                 :         if (cond) \
      84                 :             (spinfo).got_epipe = true; \
      85                 :     } while (0)
      86                 : 
      87                 : #define RESTORE_SIGPIPE(conn, spinfo) \
      88                 :     do { \
      89                 :         if (!SIGPIPE_MASKED(conn)) \
      90                 :             pq_reset_sigpipe(&(spinfo).oldsigmask, (spinfo).sigpipe_pending, \
      91                 :                              (spinfo).got_epipe); \
      92                 :     } while (0)
      93                 : #else                           /* !ENABLE_THREAD_SAFETY */
      94                 : 
      95                 : #define DECLARE_SIGPIPE_INFO(spinfo) pqsigfunc spinfo = NULL
      96                 : 
      97                 : #define DISABLE_SIGPIPE(conn, spinfo, failaction) \
      98                 :     do { \
      99                 :         if (!SIGPIPE_MASKED(conn)) \
     100                 :             spinfo = pqsignal(SIGPIPE, SIG_IGN); \
     101                 :     } while (0)
     102                 : 
     103                 : #define REMEMBER_EPIPE(spinfo, cond)
     104                 : 
     105                 : #define RESTORE_SIGPIPE(conn, spinfo) \
     106                 :     do { \
     107                 :         if (!SIGPIPE_MASKED(conn)) \
     108                 :             pqsignal(SIGPIPE, spinfo); \
     109                 :     } while (0)
     110                 : #endif                          /* ENABLE_THREAD_SAFETY */
     111                 : #else                           /* WIN32 */
     112                 : 
     113                 : #define DECLARE_SIGPIPE_INFO(spinfo)
     114                 : #define DISABLE_SIGPIPE(conn, spinfo, failaction)
     115                 : #define REMEMBER_EPIPE(spinfo, cond)
     116                 : #define RESTORE_SIGPIPE(conn, spinfo)
     117                 : #endif                          /* WIN32 */
     118                 : 
     119                 : /* ------------------------------------------------------------ */
     120                 : /*           Procedures common to all secure sessions           */
     121                 : /* ------------------------------------------------------------ */
     122                 : 
     123 ECB             : 
     124                 : int
     125 CBC           2 : PQsslInUse(PGconn *conn)
     126 EUB             : {
     127 CBC           2 :     if (!conn)
     128 UIC           0 :         return 0;
     129 GIC           2 :     return conn->ssl_in_use;
     130                 : }
     131                 : 
     132                 : /*
     133                 :  *  Exported function to allow application to tell us it's already
     134                 :  *  initialized OpenSSL.
     135 EUB             :  */
     136                 : void
     137 UIC           0 : PQinitSSL(int do_init)
     138 EUB             : {
     139                 : #ifdef USE_SSL
     140 UBC           0 :     pgtls_init_library(do_init, do_init);
     141                 : #endif
     142 UIC           0 : }
     143                 : 
     144                 : /*
     145                 :  *  Exported function to allow application to tell us it's already
     146                 :  *  initialized OpenSSL and/or libcrypto.
     147 EUB             :  */
     148                 : void
     149 UIC           0 : PQinitOpenSSL(int do_ssl, int do_crypto)
     150 EUB             : {
     151                 : #ifdef USE_SSL
     152 UBC           0 :     pgtls_init_library(do_ssl, do_crypto);
     153                 : #endif
     154 UIC           0 : }
     155                 : 
     156                 : /*
     157                 :  *  Initialize global SSL context
     158 ECB             :  */
     159                 : int
     160 CBC        9302 : pqsecure_initialize(PGconn *conn, bool do_ssl, bool do_crypto)
     161                 : {
     162 GIC        9302 :     int         r = 0;
     163 ECB             : 
     164                 : #ifdef USE_SSL
     165 GIC        9302 :     r = pgtls_init(conn, do_ssl, do_crypto);
     166 ECB             : #endif
     167                 : 
     168 GIC        9302 :     return r;
     169                 : }
     170                 : 
     171                 : /*
     172                 :  *  Begin or continue negotiating a secure session.
     173 ECB             :  */
     174                 : PostgresPollingStatusType
     175 GIC         305 : pqsecure_open_client(PGconn *conn)
     176 ECB             : {
     177                 : #ifdef USE_SSL
     178 GIC         305 :     return pgtls_open_client(conn);
     179                 : #else
     180                 :     /* shouldn't get here */
     181                 :     return PGRES_POLLING_FAILED;
     182                 : #endif
     183                 : }
     184                 : 
     185                 : /*
     186                 :  *  Close secure session.
     187 ECB             :  */
     188                 : void
     189 GIC       18875 : pqsecure_close(PGconn *conn)
     190 ECB             : {
     191                 : #ifdef USE_SSL
     192 CBC       18875 :     pgtls_close(conn);
     193                 : #endif
     194 GIC       18875 : }
     195                 : 
     196                 : /*
     197                 :  *  Read data from a secure connection.
     198                 :  *
     199                 :  * On failure, this function is responsible for appending a suitable message
     200                 :  * to conn->errorMessage.  The caller must still inspect errno, but only
     201                 :  * to determine whether to continue/retry after error.
     202 ECB             :  */
     203                 : ssize_t
     204 GIC      858474 : pqsecure_read(PGconn *conn, void *ptr, size_t len)
     205                 : {
     206                 :     ssize_t     n;
     207 ECB             : 
     208                 : #ifdef USE_SSL
     209 CBC      858474 :     if (conn->ssl_in_use)
     210                 :     {
     211 GIC         365 :         n = pgtls_read(conn, ptr, len);
     212                 :     }
     213                 :     else
     214 ECB             : #endif
     215                 : #ifdef ENABLE_GSS
     216 CBC      858109 :     if (conn->gssenc)
     217                 :     {
     218 GIC         250 :         n = pg_GSS_read(conn, ptr, len);
     219                 :     }
     220                 :     else
     221 ECB             : #endif
     222                 :     {
     223 GIC      857859 :         n = pqsecure_raw_read(conn, ptr, len);
     224 ECB             :     }
     225                 : 
     226 GIC      858474 :     return n;
     227                 : }
     228 ECB             : 
     229                 : ssize_t
     230 GIC      861206 : pqsecure_raw_read(PGconn *conn, void *ptr, size_t len)
     231 ECB             : {
     232                 :     ssize_t     n;
     233 GIC      861206 :     int         result_errno = 0;
     234 ECB             :     char        sebuf[PG_STRERROR_R_BUFLEN];
     235                 : 
     236 CBC      861206 :     n = recv(conn->sock, ptr, len, 0);
     237                 : 
     238          861206 :     if (n < 0)
     239                 :     {
     240 GIC      286167 :         result_errno = SOCK_ERRNO;
     241 ECB             : 
     242                 :         /* Set error message if appropriate */
     243 GIC      286167 :         switch (result_errno)
     244 ECB             :         {
     245                 : #ifdef EAGAIN
     246 GIC      286166 :             case EAGAIN:
     247                 : #endif
     248                 : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     249                 :             case EWOULDBLOCK:
     250                 : #endif
     251 ECB             :             case EINTR:
     252                 :                 /* no error message, caller is expected to retry */
     253 CBC      286166 :                 break;
     254                 : 
     255               1 :             case EPIPE:
     256                 :             case ECONNRESET:
     257 GNC           1 :                 libpq_append_conn_error(conn, "server closed the connection unexpectedly\n"
     258                 :                                    "\tThis probably means the server terminated abnormally\n"
     259                 :                                    "\tbefore or while processing the request.");
     260 GBC           1 :                 break;
     261                 : 
     262 UIC           0 :             default:
     263 UNC           0 :                 libpq_append_conn_error(conn, "could not receive data from server: %s",
     264                 :                                   SOCK_STRERROR(result_errno,
     265                 :                                                 sebuf, sizeof(sebuf)));
     266 UIC           0 :                 break;
     267 ECB             :         }
     268                 :     }
     269                 : 
     270                 :     /* ensure we return the intended errno to caller */
     271 GIC      861206 :     SOCK_ERRNO_SET(result_errno);
     272                 : 
     273          861206 :     return n;
     274                 : }
     275                 : 
     276                 : /*
     277                 :  *  Write data to a secure connection.
     278                 :  *
     279                 :  * Returns the number of bytes written, or a negative value (with errno
     280                 :  * set) upon failure.  The write count could be less than requested.
     281                 :  *
     282                 :  * Note that socket-level hard failures are masked from the caller,
     283                 :  * instead setting conn->write_failed and storing an error message
     284                 :  * in conn->write_err_msg; see pqsecure_raw_write.  This allows us to
     285                 :  * postpone reporting of write failures until we're sure no error
     286                 :  * message is available from the server.
     287                 :  *
     288                 :  * However, errors detected in the SSL or GSS management level are reported
     289                 :  * via a negative result, with message appended to conn->errorMessage.
     290                 :  * It's frequently unclear whether such errors should be considered read or
     291                 :  * write errors, so we don't attempt to postpone reporting them.
     292                 :  *
     293 ECB             :  * The caller must still inspect errno upon failure, but only to determine
     294                 :  * whether to continue/retry; a message has been saved someplace in any case.
     295                 :  */
     296                 : ssize_t
     297 GIC      364948 : pqsecure_write(PGconn *conn, const void *ptr, size_t len)
     298 ECB             : {
     299                 :     ssize_t     n;
     300                 : 
     301                 : #ifdef USE_SSL
     302 GIC      364948 :     if (conn->ssl_in_use)
     303                 :     {
     304             256 :         n = pgtls_write(conn, ptr, len);
     305 ECB             :     }
     306                 :     else
     307                 : #endif
     308                 : #ifdef ENABLE_GSS
     309 GIC      364692 :     if (conn->gssenc)
     310                 :     {
     311             122 :         n = pg_GSS_write(conn, ptr, len);
     312 ECB             :     }
     313                 :     else
     314                 : #endif
     315                 :     {
     316 GIC      364570 :         n = pqsecure_raw_write(conn, ptr, len);
     317                 :     }
     318                 : 
     319          364948 :     return n;
     320                 : }
     321                 : 
     322                 : /*
     323                 :  * Low-level implementation of pqsecure_write.
     324                 :  *
     325                 :  * This is used directly for an unencrypted connection.  For encrypted
     326                 :  * connections, this does the physical I/O on behalf of pgtls_write or
     327                 :  * pg_GSS_write.
     328                 :  *
     329                 :  * This function reports failure (i.e., returns a negative result) only
     330                 :  * for retryable errors such as EINTR.  Looping for such cases is to be
     331                 :  * handled at some outer level, maybe all the way up to the application.
     332                 :  * For hard failures, we set conn->write_failed and store an error message
     333                 :  * in conn->write_err_msg, but then claim to have written the data anyway.
     334                 :  * This is because we don't want to report write failures so long as there
     335                 :  * is a possibility of reading from the server and getting an error message
     336                 :  * that could explain why the connection dropped.  Many TCP stacks have
     337                 :  * race conditions such that a write failure may or may not be reported
     338                 :  * before all incoming data has been read.
     339                 :  *
     340                 :  * Note that this error behavior happens below the SSL management level when
     341                 :  * we are using SSL.  That's because at least some versions of OpenSSL are
     342 ECB             :  * too quick to report a write failure when there's still a possibility to
     343                 :  * get a more useful error from the server.
     344                 :  */
     345                 : ssize_t
     346 CBC      365397 : pqsecure_raw_write(PGconn *conn, const void *ptr, size_t len)
     347                 : {
     348                 :     ssize_t     n;
     349 GIC      365397 :     int         flags = 0;
     350          365397 :     int         result_errno = 0;
     351                 :     char        msgbuf[1024];
     352                 :     char        sebuf[PG_STRERROR_R_BUFLEN];
     353                 : 
     354                 :     DECLARE_SIGPIPE_INFO(spinfo);
     355                 : 
     356                 :     /*
     357                 :      * If we already had a write failure, we will never again try to send data
     358                 :      * on that connection.  Even if the kernel would let us, we've probably
     359 ECB             :      * lost message boundary sync with the server.  conn->write_failed
     360 EUB             :      * therefore persists until the connection is reset, and we just discard
     361                 :      * all data presented to be written.
     362                 :      */
     363 CBC      365397 :     if (conn->write_failed)
     364 LBC           0 :         return len;
     365                 : 
     366 ECB             : #ifdef MSG_NOSIGNAL
     367 GIC      365397 :     if (conn->sigpipe_flag)
     368          365397 :         flags |= MSG_NOSIGNAL;
     369 ECB             : 
     370 GIC      365397 : retry_masked:
     371 ECB             : #endif                          /* MSG_NOSIGNAL */
     372                 : 
     373 CBC      365397 :     DISABLE_SIGPIPE(conn, spinfo, return -1);
     374                 : 
     375          365397 :     n = send(conn->sock, ptr, len, flags);
     376                 : 
     377 GIC      365397 :     if (n < 0)
     378                 :     {
     379            3651 :         result_errno = SOCK_ERRNO;
     380                 : 
     381                 :         /*
     382                 :          * If we see an EINVAL, it may be because MSG_NOSIGNAL isn't available
     383 ECB             :          * on this machine.  So, clear sigpipe_flag so we don't try the flag
     384                 :          * again, and retry the send().
     385 EUB             :          */
     386                 : #ifdef MSG_NOSIGNAL
     387 GBC        3651 :         if (flags != 0 && result_errno == EINVAL)
     388                 :         {
     389 UIC           0 :             conn->sigpipe_flag = false;
     390               0 :             flags = 0;
     391               0 :             goto retry_masked;
     392 ECB             :         }
     393                 : #endif                          /* MSG_NOSIGNAL */
     394                 : 
     395                 :         /* Set error message if appropriate */
     396 GIC        3651 :         switch (result_errno)
     397                 :         {
     398                 : #ifdef EAGAIN
     399            3641 :             case EAGAIN:
     400                 : #endif
     401                 : #if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
     402 ECB             :             case EWOULDBLOCK:
     403                 : #endif
     404                 :             case EINTR:
     405                 :                 /* no error message, caller is expected to retry */
     406 CBC        3641 :                 break;
     407                 : 
     408 GIC          10 :             case EPIPE:
     409                 :                 /* Set flag for EPIPE */
     410              10 :                 REMEMBER_EPIPE(spinfo, true);
     411 ECB             : 
     412                 :                 /* FALL THRU */
     413                 : 
     414                 :             case ECONNRESET:
     415 CBC          10 :                 conn->write_failed = true;
     416                 :                 /* Store error message in conn->write_err_msg, if possible */
     417                 :                 /* (strdup failure is OK, we'll cope later) */
     418 GIC          10 :                 snprintf(msgbuf, sizeof(msgbuf),
     419 CBC          10 :                          libpq_gettext("server closed the connection unexpectedly\n"
     420 ECB             :                                        "\tThis probably means the server terminated abnormally\n"
     421                 :                                        "\tbefore or while processing the request."));
     422                 :                 /* keep newline out of translated string */
     423 GNC          10 :                 strlcat(msgbuf, "\n", sizeof(msgbuf));
     424 CBC          10 :                 conn->write_err_msg = strdup(msgbuf);
     425 ECB             :                 /* Now claim the write succeeded */
     426 GIC          10 :                 n = len;
     427 GBC          10 :                 break;
     428 EUB             : 
     429 UIC           0 :             default:
     430               0 :                 conn->write_failed = true;
     431 EUB             :                 /* Store error message in conn->write_err_msg, if possible */
     432                 :                 /* (strdup failure is OK, we'll cope later) */
     433 UIC           0 :                 snprintf(msgbuf, sizeof(msgbuf),
     434 UNC           0 :                          libpq_gettext("could not send data to server: %s"),
     435                 :                          SOCK_STRERROR(result_errno,
     436 EUB             :                                        sebuf, sizeof(sebuf)));
     437                 :                 /* keep newline out of translated string */
     438 UNC           0 :                 strlcat(msgbuf, "\n", sizeof(msgbuf));
     439 UBC           0 :                 conn->write_err_msg = strdup(msgbuf);
     440                 :                 /* Now claim the write succeeded */
     441               0 :                 n = len;
     442               0 :                 break;
     443                 :         }
     444                 :     }
     445                 : 
     446 CBC      365397 :     RESTORE_SIGPIPE(conn, spinfo);
     447                 : 
     448                 :     /* ensure we return the intended errno to caller */
     449          365397 :     SOCK_ERRNO_SET(result_errno);
     450                 : 
     451          365397 :     return n;
     452                 : }
     453                 : 
     454                 : /* Dummy versions of SSL info functions, when built without SSL support */
     455                 : #ifndef USE_SSL
     456                 : 
     457                 : void *
     458                 : PQgetssl(PGconn *conn)
     459                 : {
     460                 :     return NULL;
     461                 : }
     462                 : 
     463                 : void *
     464                 : PQsslStruct(PGconn *conn, const char *struct_name)
     465                 : {
     466                 :     return NULL;
     467                 : }
     468                 : 
     469                 : const char *
     470                 : PQsslAttribute(PGconn *conn, const char *attribute_name)
     471                 : {
     472                 :     return NULL;
     473                 : }
     474                 : 
     475                 : const char *const *
     476                 : PQsslAttributeNames(PGconn *conn)
     477                 : {
     478                 :     static const char *const result[] = {NULL};
     479                 : 
     480                 :     return result;
     481                 : }
     482                 : #endif                          /* USE_SSL */
     483                 : 
     484                 : /*
     485                 :  * Dummy versions of OpenSSL key password hook functions, when built without
     486                 :  * OpenSSL.
     487                 :  */
     488                 : #ifndef USE_OPENSSL
     489                 : 
     490                 : PQsslKeyPassHook_OpenSSL_type
     491                 : PQgetSSLKeyPassHook_OpenSSL(void)
     492                 : {
     493                 :     return NULL;
     494                 : }
     495                 : 
     496                 : void
     497                 : PQsetSSLKeyPassHook_OpenSSL(PQsslKeyPassHook_OpenSSL_type hook)
     498                 : {
     499                 :     return;
     500                 : }
     501                 : 
     502                 : int
     503                 : PQdefaultSSLKeyPassHook_OpenSSL(char *buf, int size, PGconn *conn)
     504                 : {
     505                 :     return 0;
     506                 : }
     507                 : #endif                          /* USE_OPENSSL */
     508                 : 
     509                 : /* Dummy version of GSSAPI information functions, when built without GSS support */
     510                 : #ifndef ENABLE_GSS
     511                 : 
     512                 : void *
     513                 : PQgetgssctx(PGconn *conn)
     514                 : {
     515                 :     return NULL;
     516                 : }
     517                 : 
     518                 : int
     519                 : PQgssEncInUse(PGconn *conn)
     520                 : {
     521                 :     return 0;
     522                 : }
     523                 : 
     524                 : #endif                          /* ENABLE_GSS */
     525                 : 
     526                 : 
     527                 : #if defined(ENABLE_THREAD_SAFETY) && !defined(WIN32)
     528                 : 
     529                 : /*
     530                 :  *  Block SIGPIPE for this thread.  This prevents send()/write() from exiting
     531                 :  *  the application.
     532                 :  */
     533                 : int
     534 UBC           0 : pq_block_sigpipe(sigset_t *osigset, bool *sigpipe_pending)
     535                 : {
     536                 :     sigset_t    sigpipe_sigset;
     537                 :     sigset_t    sigset;
     538                 : 
     539               0 :     sigemptyset(&sigpipe_sigset);
     540               0 :     sigaddset(&sigpipe_sigset, SIGPIPE);
     541                 : 
     542                 :     /* Block SIGPIPE and save previous mask for later reset */
     543               0 :     SOCK_ERRNO_SET(pthread_sigmask(SIG_BLOCK, &sigpipe_sigset, osigset));
     544               0 :     if (SOCK_ERRNO)
     545               0 :         return -1;
     546                 : 
     547                 :     /* We can have a pending SIGPIPE only if it was blocked before */
     548               0 :     if (sigismember(osigset, SIGPIPE))
     549                 :     {
     550                 :         /* Is there a pending SIGPIPE? */
     551               0 :         if (sigpending(&sigset) != 0)
     552               0 :             return -1;
     553                 : 
     554               0 :         if (sigismember(&sigset, SIGPIPE))
     555               0 :             *sigpipe_pending = true;
     556                 :         else
     557               0 :             *sigpipe_pending = false;
     558                 :     }
     559                 :     else
     560               0 :         *sigpipe_pending = false;
     561                 : 
     562               0 :     return 0;
     563                 : }
     564                 : 
     565                 : /*
     566                 :  *  Discard any pending SIGPIPE and reset the signal mask.
     567                 :  *
     568                 :  * Note: we are effectively assuming here that the C library doesn't queue
     569                 :  * up multiple SIGPIPE events.  If it did, then we'd accidentally leave
     570                 :  * ours in the queue when an event was already pending and we got another.
     571                 :  * As long as it doesn't queue multiple events, we're OK because the caller
     572                 :  * can't tell the difference.
     573                 :  *
     574                 :  * The caller should say got_epipe = false if it is certain that it
     575                 :  * didn't get an EPIPE error; in that case we'll skip the clear operation
     576                 :  * and things are definitely OK, queuing or no.  If it got one or might have
     577                 :  * gotten one, pass got_epipe = true.
     578                 :  *
     579                 :  * We do not want this to change errno, since if it did that could lose
     580                 :  * the error code from a preceding send().  We essentially assume that if
     581                 :  * we were able to do pq_block_sigpipe(), this can't fail.
     582                 :  */
     583                 : void
     584               0 : pq_reset_sigpipe(sigset_t *osigset, bool sigpipe_pending, bool got_epipe)
     585                 : {
     586               0 :     int         save_errno = SOCK_ERRNO;
     587                 :     int         signo;
     588                 :     sigset_t    sigset;
     589                 : 
     590                 :     /* Clear SIGPIPE only if none was pending */
     591               0 :     if (got_epipe && !sigpipe_pending)
     592                 :     {
     593               0 :         if (sigpending(&sigset) == 0 &&
     594               0 :             sigismember(&sigset, SIGPIPE))
     595                 :         {
     596                 :             sigset_t    sigpipe_sigset;
     597                 : 
     598               0 :             sigemptyset(&sigpipe_sigset);
     599               0 :             sigaddset(&sigpipe_sigset, SIGPIPE);
     600                 : 
     601               0 :             sigwait(&sigpipe_sigset, &signo);
     602                 :         }
     603                 :     }
     604                 : 
     605                 :     /* Restore saved block mask */
     606               0 :     pthread_sigmask(SIG_SETMASK, osigset, NULL);
     607                 : 
     608               0 :     SOCK_ERRNO_SET(save_errno);
     609               0 : }
     610                 : 
     611                 : #endif                          /* ENABLE_THREAD_SAFETY && !WIN32 */
        

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