LCOV - code coverage report
Current view: top level - src/interfaces/libpq - thread.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 4 4 100.0 %
Date: 2017-09-29 15:12:54 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * thread.c
       4             :  *
       5             :  *        Prototypes and macros around system calls, used to help make
       6             :  *        threaded libraries reentrant and safe to use from threaded applications.
       7             :  *
       8             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       9             :  *
      10             :  * src/port/thread.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : 
      15             : #include "c.h"
      16             : 
      17             : #include <pwd.h>
      18             : 
      19             : 
      20             : /*
      21             :  *  Threading sometimes requires specially-named versions of functions
      22             :  *  that return data in static buffers, like strerror_r() instead of
      23             :  *  strerror().  Other operating systems use pthread_setspecific()
      24             :  *  and pthread_getspecific() internally to allow standard library
      25             :  *  functions to return static data to threaded applications. And some
      26             :  *  operating systems have neither.
      27             :  *
      28             :  *  Additional confusion exists because many operating systems that
      29             :  *  use pthread_setspecific/pthread_getspecific() also have *_r versions
      30             :  *  of standard library functions for compatibility with operating systems
      31             :  *  that require them.  However, internally, these *_r functions merely
      32             :  *  call the thread-safe standard library functions.
      33             :  *
      34             :  *  For example, BSD/OS 4.3 uses Bind 8.2.3 for getpwuid().  Internally,
      35             :  *  getpwuid() calls pthread_setspecific/pthread_getspecific() to return
      36             :  *  static data to the caller in a thread-safe manner.  However, BSD/OS
      37             :  *  also has getpwuid_r(), which merely calls getpwuid() and shifts
      38             :  *  around the arguments to match the getpwuid_r() function declaration.
      39             :  *  Therefore, while BSD/OS has getpwuid_r(), it isn't required.  It also
      40             :  *  doesn't have strerror_r(), so we can't fall back to only using *_r
      41             :  *  functions for threaded programs.
      42             :  *
      43             :  *  The current setup is to try threading in this order:
      44             :  *
      45             :  *      use *_r function names if they exit
      46             :  *          (*_THREADSAFE=yes)
      47             :  *      use non-*_r functions if they are thread-safe
      48             :  *
      49             :  *  One thread-safe solution for gethostbyname() might be to use getaddrinfo().
      50             :  *
      51             :  *  Run src/test/thread to test if your operating system has thread-safe
      52             :  *  non-*_r functions.
      53             :  */
      54             : 
      55             : 
      56             : /*
      57             :  * Wrapper around strerror and strerror_r to use the former if it is
      58             :  * available and also return a more useful value (the error string).
      59             :  */
      60             : char *
      61           2 : pqStrerror(int errnum, char *strerrbuf, size_t buflen)
      62             : {
      63             : #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_STRERROR_R)
      64             :     /* reentrant strerror_r is available */
      65             : #ifdef STRERROR_R_INT
      66             :     /* SUSv3 version */
      67             :     if (strerror_r(errnum, strerrbuf, buflen) == 0)
      68             :         return strerrbuf;
      69             :     else
      70             :         return "Unknown error";
      71             : #else
      72             :     /* GNU libc */
      73           2 :     return strerror_r(errnum, strerrbuf, buflen);
      74             : #endif
      75             : #else
      76             :     /* no strerror_r() available, just use strerror */
      77             :     strlcpy(strerrbuf, strerror(errnum), buflen);
      78             : 
      79             :     return strerrbuf;
      80             : #endif
      81             : }
      82             : 
      83             : /*
      84             :  * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
      85             :  * behaviour, if that function is not available or required.
      86             :  *
      87             :  * Per POSIX, the possible cases are:
      88             :  * success: returns zero, *result is non-NULL
      89             :  * uid not found: returns zero, *result is NULL
      90             :  * error during lookup: returns an errno code, *result is NULL
      91             :  * (caller should *not* assume that the errno variable is set)
      92             :  */
      93             : #ifndef WIN32
      94             : int
      95         403 : pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
      96             :            size_t buflen, struct passwd **result)
      97             : {
      98             : #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R)
      99         403 :     return getpwuid_r(uid, resultbuf, buffer, buflen, result);
     100             : #else
     101             :     /* no getpwuid_r() available, just use getpwuid() */
     102             :     errno = 0;
     103             :     *result = getpwuid(uid);
     104             :     /* paranoia: ensure we return zero on success */
     105             :     return (*result == NULL) ? errno : 0;
     106             : #endif
     107             : }
     108             : #endif
     109             : 
     110             : /*
     111             :  * Wrapper around gethostbyname() or gethostbyname_r() to mimic
     112             :  * POSIX gethostbyname_r() behaviour, if it is not available or required.
     113             :  * This function is called _only_ by our getaddinfo() portability function.
     114             :  */
     115             : #ifndef HAVE_GETADDRINFO
     116             : int
     117             : pqGethostbyname(const char *name,
     118             :                 struct hostent *resultbuf,
     119             :                 char *buffer, size_t buflen,
     120             :                 struct hostent **result,
     121             :                 int *herrno)
     122             : {
     123             : #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
     124             : 
     125             :     /*
     126             :      * broken (well early POSIX draft) gethostbyname_r() which returns 'struct
     127             :      * hostent *'
     128             :      */
     129             :     *result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
     130             :     return (*result == NULL) ? -1 : 0;
     131             : #else
     132             : 
     133             :     /* no gethostbyname_r(), just use gethostbyname() */
     134             :     *result = gethostbyname(name);
     135             : 
     136             :     if (*result != NULL)
     137             :         *herrno = h_errno;
     138             : 
     139             :     if (*result != NULL)
     140             :         return 0;
     141             :     else
     142             :         return -1;
     143             : #endif
     144             : }
     145             : 
     146             : #endif

Generated by: LCOV version 1.11