]> granicus.if.org Git - postgresql/blob - src/port/thread.c
Make NEED_REENTRANT_FUNC_NAMES _require_ *_r functions, and add tests to
[postgresql] / src / port / thread.c
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-2003, PostgreSQL Global Development Group
9  *
10  * $Id: thread.c,v 1.4 2003/08/16 15:35:51 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14
15 #include "postgres.h"
16
17 /*
18  *      Threading sometimes requires specially-named versions of functions
19  *      that return data in static buffers, like strerror_r() instead of
20  *      strerror().  Other operating systems use pthread_setspecific()
21  *      and pthread_getspecific() internally to allow standard library
22  *      functions to return static data to threaded applications.
23  *
24  *      Additional confusion exists because many operating systems that
25  *      use pthread_setspecific/pthread_getspecific() also have *_r versions
26  *      of standard library functions for compatibility with operating systems
27  *      that require them.  However, internally, these *_r functions merely
28  *      call the thread-safe standard library functions.
29  *
30  *      For example, BSD/OS 4.3 uses Bind 8.2.3 for getpwuid().  Internally,
31  *      getpwuid() calls pthread_setspecific/pthread_getspecific() to return
32  *      static data to the caller in a thread-safe manner.  However, BSD/OS
33  *      also has getpwuid_r(), which merely calls getpwuid() and shifts
34  *      around the arguments to match the getpwuid_r() function declaration.
35  *      Therefore, while BSD/OS has getpwuid_r(), it isn't required.  It also
36  *      doesn't have strerror_r(), so we can't fall back to only using *_r
37  *      functions for threaded programs.
38  *
39  *      The current setup is to assume either all standard functions are
40  *      thread-safe (NEED_REENTRANT_FUNC_NAMES=no), or the operating system
41  *      requires reentrant function names (NEED_REENTRANT_FUNC_NAMES=yes).
42  */
43  
44
45 /*
46  * Wrapper around strerror and strerror_r to use the former if it is
47  * available and also return a more useful value (the error string).
48  */
49 char *
50 pqStrerror(int errnum, char *strerrbuf, size_t buflen)
51 {
52 #if defined(USE_THREADS) && defined(NEED_REENTRANT_FUNC_NAMES)
53         /* reentrant strerror_r is available */
54         /* some early standards had strerror_r returning char * */
55         strerror_r(errnum, strerrbuf, buflen);
56         return (strerrbuf);
57 #else
58         /* no strerror_r() available, just use strerror */
59         return strerror(errnum);
60 #endif
61 }
62
63 /*
64  * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
65  * behaviour, if it is not available or required.
66  */
67 int
68 pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
69                    size_t buflen, struct passwd **result)
70 {
71 #if defined(USE_THREADS) && defined(NEED_REENTRANT_FUNC_NAMES)
72         /*
73          * Early POSIX draft of getpwuid_r() returns 'struct passwd *'.
74          *    getpwuid_r(uid, resultbuf, buffer, buflen)
75          * Do we need to support it?  bjm 2003-08-14
76          */
77         /* POSIX version */
78         getpwuid_r(uid, resultbuf, buffer, buflen, result);
79 #else
80         /* no getpwuid_r() available, just use getpwuid() */
81         *result = getpwuid(uid);
82 #endif
83         return (*result == NULL) ? -1 : 0;
84 }
85
86 /*
87  * Wrapper around gethostbyname() or gethostbyname_r() to mimic
88  * POSIX gethostbyname_r() behaviour, if it is not available or required.
89  */
90 int
91 pqGethostbyname(const char *name,
92                                 struct hostent *resbuf,
93                                 char *buf, size_t buflen,
94                                 struct hostent **result,
95                                 int *herrno)
96 {
97 #if defined(USE_THREADS) && defined(NEED_REENTRANT_FUNC_NAMES)
98         /*
99          * broken (well early POSIX draft) gethostbyname_r() which returns
100          * 'struct hostent *'
101          */
102         *result = gethostbyname_r(name, resbuf, buf, buflen, herrno);
103         return (*result == NULL) ? -1 : 0;
104 #else
105         /* no gethostbyname_r(), just use gethostbyname() */
106         *result = gethostbyname(name);
107         if (*result != NULL)
108                 return 0;
109         else
110         {
111                 *herrno = h_errno;
112                 return -1;
113         }
114 #endif
115 }