00001 /*------------------------------------------------------------------------- 00002 * 00003 * thread.c 00004 * 00005 * Prototypes and macros around system calls, used to help make 00006 * threaded libraries reentrant and safe to use from threaded applications. 00007 * 00008 * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group 00009 * 00010 * src/port/thread.c 00011 * 00012 *------------------------------------------------------------------------- 00013 */ 00014 00015 #include "c.h" 00016 00017 #include <pwd.h> 00018 00019 00020 /* 00021 * Threading sometimes requires specially-named versions of functions 00022 * that return data in static buffers, like strerror_r() instead of 00023 * strerror(). Other operating systems use pthread_setspecific() 00024 * and pthread_getspecific() internally to allow standard library 00025 * functions to return static data to threaded applications. And some 00026 * operating systems have neither. 00027 * 00028 * Additional confusion exists because many operating systems that 00029 * use pthread_setspecific/pthread_getspecific() also have *_r versions 00030 * of standard library functions for compatibility with operating systems 00031 * that require them. However, internally, these *_r functions merely 00032 * call the thread-safe standard library functions. 00033 * 00034 * For example, BSD/OS 4.3 uses Bind 8.2.3 for getpwuid(). Internally, 00035 * getpwuid() calls pthread_setspecific/pthread_getspecific() to return 00036 * static data to the caller in a thread-safe manner. However, BSD/OS 00037 * also has getpwuid_r(), which merely calls getpwuid() and shifts 00038 * around the arguments to match the getpwuid_r() function declaration. 00039 * Therefore, while BSD/OS has getpwuid_r(), it isn't required. It also 00040 * doesn't have strerror_r(), so we can't fall back to only using *_r 00041 * functions for threaded programs. 00042 * 00043 * The current setup is to try threading in this order: 00044 * 00045 * use *_r function names if they exit 00046 * (*_THREADSAFE=yes) 00047 * use non-*_r functions if they are thread-safe 00048 * 00049 * One thread-safe solution for gethostbyname() might be to use getaddrinfo(). 00050 * 00051 * Run src/test/thread to test if your operating system has thread-safe 00052 * non-*_r functions. 00053 */ 00054 00055 00056 /* 00057 * Wrapper around strerror and strerror_r to use the former if it is 00058 * available and also return a more useful value (the error string). 00059 */ 00060 char * 00061 pqStrerror(int errnum, char *strerrbuf, size_t buflen) 00062 { 00063 #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_STRERROR_R) 00064 /* reentrant strerror_r is available */ 00065 #ifdef STRERROR_R_INT 00066 /* SUSv3 version */ 00067 if (strerror_r(errnum, strerrbuf, buflen) == 0) 00068 return strerrbuf; 00069 else 00070 return "Unknown error"; 00071 #else 00072 /* GNU libc */ 00073 return strerror_r(errnum, strerrbuf, buflen); 00074 #endif 00075 #else 00076 /* no strerror_r() available, just use strerror */ 00077 strlcpy(strerrbuf, strerror(errnum), buflen); 00078 00079 return strerrbuf; 00080 #endif 00081 } 00082 00083 /* 00084 * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r() 00085 * behaviour, if it is not available or required. 00086 */ 00087 #ifndef WIN32 00088 int 00089 pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer, 00090 size_t buflen, struct passwd ** result) 00091 { 00092 #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETPWUID_R) 00093 00094 #ifdef GETPWUID_R_5ARG 00095 /* POSIX version */ 00096 getpwuid_r(uid, resultbuf, buffer, buflen, result); 00097 #else 00098 00099 /* 00100 * Early POSIX draft of getpwuid_r() returns 'struct passwd *'. 00101 * getpwuid_r(uid, resultbuf, buffer, buflen) 00102 */ 00103 *result = getpwuid_r(uid, resultbuf, buffer, buflen); 00104 #endif 00105 #else 00106 00107 /* no getpwuid_r() available, just use getpwuid() */ 00108 *result = getpwuid(uid); 00109 #endif 00110 00111 return (*result == NULL) ? -1 : 0; 00112 } 00113 #endif 00114 00115 /* 00116 * Wrapper around gethostbyname() or gethostbyname_r() to mimic 00117 * POSIX gethostbyname_r() behaviour, if it is not available or required. 00118 * This function is called _only_ by our getaddinfo() portability function. 00119 */ 00120 #ifndef HAVE_GETADDRINFO 00121 int 00122 pqGethostbyname(const char *name, 00123 struct hostent * resultbuf, 00124 char *buffer, size_t buflen, 00125 struct hostent ** result, 00126 int *herrno) 00127 { 00128 #if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_GETHOSTBYNAME_R) 00129 00130 /* 00131 * broken (well early POSIX draft) gethostbyname_r() which returns 'struct 00132 * hostent *' 00133 */ 00134 *result = gethostbyname_r(name, resultbuf, buffer, buflen, herrno); 00135 return (*result == NULL) ? -1 : 0; 00136 #else 00137 00138 /* no gethostbyname_r(), just use gethostbyname() */ 00139 *result = gethostbyname(name); 00140 00141 if (*result != NULL) 00142 *herrno = h_errno; 00143 00144 if (*result != NULL) 00145 return 0; 00146 else 00147 return -1; 00148 #endif 00149 } 00150 00151 #endif