LCOV - code coverage report
Current view: top level - src/port - thread.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 2 5 40.0 %
Date: 2019-11-13 22:07:24 Functions: 1 1 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-2019, 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 getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
      58             :  * behaviour, if that function is not available or required.
      59             :  *
      60             :  * Per POSIX, the possible cases are:
      61             :  * success: returns zero, *result is non-NULL
      62             :  * uid not found: returns zero, *result is NULL
      63             :  * error during lookup: returns an errno code, *result is NULL
      64             :  * (caller should *not* assume that the errno variable is set)
      65             :  */
      66             : #ifndef WIN32
      67             : int
      68       14214 : pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
      69             :            size_t buflen, struct passwd **result)
      70             : {
      71             : #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R)
      72       14214 :     return getpwuid_r(uid, resultbuf, buffer, buflen, result);
      73             : #else
      74             :     /* no getpwuid_r() available, just use getpwuid() */
      75           0 :     errno = 0;
      76           0 :     *result = getpwuid(uid);
      77             :     /* paranoia: ensure we return zero on success */
      78           0 :     return (*result == NULL) ? errno : 0;
      79             : #endif
      80             : }
      81             : #endif
      82             : 
      83             : /*
      84             :  * Wrapper around gethostbyname() or gethostbyname_r() to mimic
      85             :  * POSIX gethostbyname_r() behaviour, if it is not available or required.
      86             :  * This function is called _only_ by our getaddrinfo() portability function.
      87             :  */
      88             : #ifndef HAVE_GETADDRINFO
      89             : int
      90             : pqGethostbyname(const char *name,
      91             :                 struct hostent *resultbuf,
      92             :                 char *buffer, size_t buflen,
      93             :                 struct hostent **result,
      94             :                 int *herrno)
      95             : {
      96             : #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R)
      97             : 
      98             :     /*
      99             :      * broken (well early POSIX draft) gethostbyname_r() which returns 'struct
     100             :      * hostent *'
     101             :      */
     102             :     *result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno);
     103             :     return (*result == NULL) ? -1 : 0;
     104             : #else
     105             : 
     106             :     /* no gethostbyname_r(), just use gethostbyname() */
     107             :     *result = gethostbyname(name);
     108             : 
     109             :     if (*result != NULL)
     110             :         *herrno = h_errno;
     111             : 
     112             :     if (*result != NULL)
     113             :         return 0;
     114             :     else
     115             :         return -1;
     116             : #endif
     117             : }
     118             : 
     119             : #endif

Generated by: LCOV version 1.13