Index: configure.in =================================================================== RCS file: /cvsroot/pgsql-server/configure.in,v retrieving revision 1.287 diff -c -c -r1.287 configure.in *** configure.in 12 Sep 2003 16:10:26 -0000 1.287 --- configure.in 13 Sep 2003 14:47:43 -0000 *************** *** 1031,1047 **** # One trick here is that if we don't call AC_CHECK_FUNCS, the # functions are marked "not found", which is perfect. # ! if test "$enable_thread_safety" = yes -a "$NEED_REENTRANT_FUNC_NAMES" = yes ; then _CFLAGS="$CFLAGS" _LIBS="$LIBS" CFLAGS="$CFLAGS $THREAD_CFLAGS" LIBS="$LIBS $THREAD_LIBS" ! AC_CHECK_FUNC(strerror_r, ! [], [AC_MSG_ERROR([strerror_r not found, required on this platform for --enable-thread-safety])]) ! AC_CHECK_FUNC(getpwuid_r, ! [], [AC_MSG_ERROR([getpwuid_r not found, required on this platform for --enable-thread-safety])]) ! AC_CHECK_FUNC(gethostbyname_r, ! [], [AC_MSG_ERROR([gethostbyname_r not found, required on this platform for --enable-thread-safety])]) CFLAGS="$_CFLAGS" LIBS="$_LIBS" fi --- 1031,1042 ---- # One trick here is that if we don't call AC_CHECK_FUNCS, the # functions are marked "not found", which is perfect. # ! if test "$enable_thread_safety" = yes -a "$NEED_REENTRANT_FUNCS" = yes ; then _CFLAGS="$CFLAGS" _LIBS="$LIBS" CFLAGS="$CFLAGS $THREAD_CFLAGS" LIBS="$LIBS $THREAD_LIBS" ! AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r]) CFLAGS="$_CFLAGS" LIBS="$_LIBS" fi Index: src/include/port.h =================================================================== RCS file: /cvsroot/pgsql-server/src/include/port.h,v retrieving revision 1.13 diff -c -c -r1.13 port.h *** src/include/port.h 5 Sep 2003 17:43:39 -0000 1.13 --- src/include/port.h 13 Sep 2003 14:47:46 -0000 *************** *** 114,124 **** #ifndef WIN32 extern int pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer, ! size_t buflen, struct passwd ** result); #endif extern int pqGethostbyname(const char *name, ! struct hostent * resbuf, ! char *buf, size_t buflen, ! struct hostent ** result, int *herrno); --- 114,124 ---- #ifndef WIN32 extern int pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer, ! size_t buflen, struct passwd **result); #endif extern int pqGethostbyname(const char *name, ! struct hostent *resultbuf, ! char *buffer, size_t buflen, ! struct hostent **result, int *herrno); Index: src/port/thread.c =================================================================== RCS file: /cvsroot/pgsql-server/src/port/thread.c,v retrieving revision 1.6 diff -c -c -r1.6 thread.c *** src/port/thread.c 5 Sep 2003 17:43:40 -0000 1.6 --- src/port/thread.c 13 Sep 2003 14:47:47 -0000 *************** *** 14,25 **** #include "postgres.h" /* * Threading sometimes requires specially-named versions of functions * that return data in static buffers, like strerror_r() instead of * strerror(). Other operating systems use pthread_setspecific() * and pthread_getspecific() internally to allow standard library ! * functions to return static data to threaded applications. * * Additional confusion exists because many operating systems that * use pthread_setspecific/pthread_getspecific() also have *_r versions --- 14,30 ---- #include "postgres.h" + #include + #include + #include + /* * Threading sometimes requires specially-named versions of functions * that return data in static buffers, like strerror_r() instead of * strerror(). Other operating systems use pthread_setspecific() * and pthread_getspecific() internally to allow standard library ! * functions to return static data to threaded applications. And some ! * operating systems have neither, meaning we have to do our own locking. * * Additional confusion exists because many operating systems that * use pthread_setspecific/pthread_getspecific() also have *_r versions *************** *** 36,46 **** * doesn't have strerror_r(), so we can't fall back to only using *_r * functions for threaded programs. * ! * The current setup is to assume either all standard functions are ! * thread-safe (NEED_REENTRANT_FUNC_NAMES=no), or the operating system ! * requires reentrant function names (NEED_REENTRANT_FUNC_NAMES=yes). * Compile and run src/tools/test_thread_funcs.c to see if your operating ! * system requires reentrant function names. */ --- 41,55 ---- * doesn't have strerror_r(), so we can't fall back to only using *_r * functions for threaded programs. * ! * The current setup is to try threading in this order: ! * ! * use non-*_r function names if they are all thread-safe ! * (NEED_REENTRANT_FUNCS=no) ! * use *_r functions if they exist (configure test) ! * do our own locking and copying of non-threadsafe functions ! * * Compile and run src/tools/test_thread_funcs.c to see if your operating ! * system has thread-safe non-*_r functions. */ *************** *** 51,64 **** char * pqStrerror(int errnum, char *strerrbuf, size_t buflen) { ! #if defined(USE_THREADS) && defined(NEED_REENTRANT_FUNC_NAMES) /* reentrant strerror_r is available */ /* some early standards had strerror_r returning char * */ strerror_r(errnum, strerrbuf, buflen); ! return (strerrbuf); #else /* no strerror_r() available, just use strerror */ ! return strerror(errnum); #endif } --- 60,86 ---- char * pqStrerror(int errnum, char *strerrbuf, size_t buflen) { ! #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && defined(HAVE_STRERROR_R) /* reentrant strerror_r is available */ /* some early standards had strerror_r returning char * */ strerror_r(errnum, strerrbuf, buflen); ! return strerrbuf; ! #else + + #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_STRERROR_R) + static pthread_mutex_t strerror_lock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&strerror_lock); + #endif + /* no strerror_r() available, just use strerror */ ! StrNCpy(strerrbuf, strerror(errnum), buflen); ! ! #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_STRERROR_R) ! pthread_mutex_unlock(&strerror_lock); ! #endif ! ! return strerrbuf; #endif } *************** *** 71,77 **** pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result) { ! #if defined(USE_THREADS) && defined(NEED_REENTRANT_FUNC_NAMES) /* * Early POSIX draft of getpwuid_r() returns 'struct passwd *'. * getpwuid_r(uid, resultbuf, buffer, buflen) --- 93,99 ---- pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer, size_t buflen, struct passwd **result) { ! #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && defined(HAVE_GETPWUID_R) /* * Early POSIX draft of getpwuid_r() returns 'struct passwd *'. * getpwuid_r(uid, resultbuf, buffer, buflen) *************** *** 79,87 **** --- 101,152 ---- */ /* POSIX version */ getpwuid_r(uid, resultbuf, buffer, buflen, result); + #else + + #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETPWUID_R) + static pthread_mutex_t getpwuid_lock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&getpwuid_lock); + #endif + /* no getpwuid_r() available, just use getpwuid() */ *result = getpwuid(uid); + + #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETPWUID_R) + + /* Use 'buffer' memory for storage of strings used by struct passwd */ + if (*result && + strlen((*result)->pw_name) + 1 + + strlen((*result)->pw_passwd) + 1 + + strlen((*result)->pw_gecos) + 1 + + /* skip class if it exists */ + strlen((*result)->pw_dir) + 1 + + strlen((*result)->pw_shell) + 1 <= buflen) + { + memcpy(resultbuf, *result, sizeof(struct passwd)); + strcpy(buffer, (*result)->pw_name); + resultbuf->pw_name = buffer; + buffer += strlen(resultbuf->pw_name) + 1; + strcpy(buffer, (*result)->pw_passwd); + resultbuf->pw_passwd = buffer; + buffer += strlen(resultbuf->pw_passwd) + 1; + strcpy(buffer, (*result)->pw_gecos); + resultbuf->pw_gecos = buffer; + buffer += strlen(resultbuf->pw_gecos) + 1; + strcpy(buffer, (*result)->pw_dir); + resultbuf->pw_dir = buffer; + buffer += strlen(resultbuf->pw_dir) + 1; + strcpy(buffer, (*result)->pw_shell); + resultbuf->pw_shell = buffer; + buffer += strlen(resultbuf->pw_shell) + 1; + + *result = resultbuf; + } + else + *result = NULL; + + pthread_mutex_unlock(&getpwuid_lock); + #endif #endif return (*result == NULL) ? -1 : 0; } *************** *** 93,119 **** */ int pqGethostbyname(const char *name, ! struct hostent *resbuf, ! char *buf, size_t buflen, struct hostent **result, int *herrno) { ! #if defined(USE_THREADS) && defined(NEED_REENTRANT_FUNC_NAMES) /* * broken (well early POSIX draft) gethostbyname_r() which returns * 'struct hostent *' */ ! *result = gethostbyname_r(name, resbuf, buf, buflen, herrno); return (*result == NULL) ? -1 : 0; #else /* no gethostbyname_r(), just use gethostbyname() */ *result = gethostbyname(name); if (*result != NULL) return 0; else - { - *herrno = h_errno; return -1; - } #endif } --- 158,258 ---- */ int pqGethostbyname(const char *name, ! struct hostent *resultbuf, ! char *buffer, size_t buflen, struct hostent **result, int *herrno) { ! #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && defined(HAVE_GETHOSTBYNAME_R) /* * broken (well early POSIX draft) gethostbyname_r() which returns * 'struct hostent *' */ ! *result = gethostbyname_r(name, resbuf, buffer, buflen, herrno); return (*result == NULL) ? -1 : 0; + #else + + #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R) + static pthread_mutex_t gethostbyname_lock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&gethostbyname_lock); + #endif + /* no gethostbyname_r(), just use gethostbyname() */ *result = gethostbyname(name); + + #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R) + + /* + * Use 'buffer' memory for storage of structures used by struct hostent. + * The layout is: + * + * addr pointers + * alias pointers + * addr structures + * alias structures + * name + */ + if (*result) + { + int i, pointers = 2 /* for nulls */, len = 0; + char **pbuffer; + + for (i = 0; (*result)->h_addr_list[i]; i++, pointers++) + len += (*result)->h_length; + for (i = 0; (*result)->h_aliases[i]; i++, pointers++) + len += (*result)->h_length; + + if (MAXALIGN(len) + pointers * sizeof(char *) + strlen((*result)->h_name) + 1 <= buflen) + { + memcpy(resultbuf, *result, sizeof(struct hostent)); + + pbuffer = (char **)buffer; + resultbuf->h_addr_list = pbuffer; + buffer += pointers * sizeof(char *); + + for (i = 0; (*result)->h_addr_list[i]; i++, pbuffer++) + { + memcpy(buffer, (*result)->h_addr_list[i], (*result)->h_length); + resultbuf->h_addr_list[i] = buffer; + buffer += (*result)->h_length; + } + resultbuf->h_addr_list[i] = NULL; + pbuffer++; + + resultbuf->h_aliases = pbuffer; + + for (i = 0; (*result)->h_aliases[i]; i++, pbuffer++) + { + memcpy(buffer, (*result)->h_aliases[i], (*result)->h_length); + resultbuf->h_aliases[i] = buffer; + buffer += (*result)->h_length; + } + resultbuf->h_aliases[i] = NULL; + pbuffer++; + + /* Place at end for cleaner alignment */ + strcpy(buffer, (*result)->h_name); + resultbuf->h_name = buffer; + buffer += strlen(resultbuf->h_name) + 1; + + *result = resultbuf; + } + else + *result = NULL; + } + #endif + + if (*result != NULL) + *herrno = h_errno; + + #if defined(FRONTEND) && defined(USE_THREADS) && defined(NEED_REENTRANT_FUNCS) && !defined(HAVE_GETHOSTBYNAME_R) + pthread_mutex_unlock(&gethostbyname_lock); + #endif + if (*result != NULL) return 0; else return -1; #endif } Index: src/template/bsdi =================================================================== RCS file: /cvsroot/pgsql-server/src/template/bsdi,v retrieving revision 1.13 diff -c -c -r1.13 bsdi *** src/template/bsdi 3 Sep 2003 20:54:20 -0000 1.13 --- src/template/bsdi 13 Sep 2003 14:47:47 -0000 *************** *** 11,14 **** esac SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNC_NAMES=no # verified 4.3 2003-09-03 --- 11,14 ---- esac SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNCS=no # verified 4.3 2003-09-03 Index: src/template/freebsd =================================================================== RCS file: /cvsroot/pgsql-server/src/template/freebsd,v retrieving revision 1.20 diff -c -c -r1.20 freebsd *** src/template/freebsd 12 Sep 2003 16:49:34 -0000 1.20 --- src/template/freebsd 13 Sep 2003 14:47:47 -0000 *************** *** 4,11 **** alpha*) CFLAGS="$CFLAGS -O" ;; esac ! SUPPORTS_THREADS=no # 4.8, 5.1 2003-09-12 ! NEED_REENTRANT_FUNC_NAMES=no case $host_os in freebsd2*|freebsd3*|freebsd4*) --- 4,11 ---- alpha*) CFLAGS="$CFLAGS -O" ;; esac ! SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNCS=yes # 4.8, 5.1 2003-09-12 case $host_os in freebsd2*|freebsd3*|freebsd4*) Index: src/template/linux =================================================================== RCS file: /cvsroot/pgsql-server/src/template/linux,v retrieving revision 1.13 diff -c -c -r1.13 linux *** src/template/linux 3 Sep 2003 22:34:08 -0000 1.13 --- src/template/linux 13 Sep 2003 14:47:47 -0000 *************** *** 1,7 **** CFLAGS=-O2 SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNC_NAMES=yes # verified glibc 2.1 2003-09-03 THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" THREAD_LIBS="-lpthread" --- 1,7 ---- CFLAGS=-O2 SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNCS=yes # verified glibc 2.1 2003-09-03 THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS" THREAD_LIBS="-lpthread" Index: src/template/netbsd =================================================================== RCS file: /cvsroot/pgsql-server/src/template/netbsd,v retrieving revision 1.10 diff -c -c -r1.10 netbsd *** src/template/netbsd 16 Aug 2003 15:35:51 -0000 1.10 --- src/template/netbsd 13 Sep 2003 14:47:47 -0000 *************** *** 1,4 **** CFLAGS='-O2 -pipe' SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNC_NAMES=no --- 1,4 ---- CFLAGS='-O2 -pipe' SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNCS=no Index: src/template/osf =================================================================== RCS file: /cvsroot/pgsql-server/src/template/osf,v retrieving revision 1.7 diff -c -c -r1.7 osf *** src/template/osf 16 Aug 2003 15:35:51 -0000 1.7 --- src/template/osf 13 Sep 2003 14:47:47 -0000 *************** *** 6,10 **** fi SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNC_NAMES=no THREAD_CFLAGS="-pthread" --- 6,10 ---- fi SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNCS=no # 4.0 2003-09-13 THREAD_CFLAGS="-pthread" Index: src/template/solaris =================================================================== RCS file: /cvsroot/pgsql-server/src/template/solaris,v retrieving revision 1.2 diff -c -c -r1.2 solaris *** src/template/solaris 21 Oct 2000 22:36:14 -0000 1.2 --- src/template/solaris 13 Sep 2003 14:47:47 -0000 *************** *** 4,6 **** --- 4,11 ---- CC="$CC -Xa" # relaxed ISO C mode CFLAGS=-v # -v is like gcc -Wall fi + + SUPPORTS_THREADS=yes + NEED_REENTRANT_FUNCS=yes # 5.6 2003-09-13 + THREAD_CFLAGS="-pthread" + Index: src/template/unixware =================================================================== RCS file: /cvsroot/pgsql-server/src/template/unixware,v retrieving revision 1.21 diff -c -c -r1.21 unixware *** src/template/unixware 3 Sep 2003 20:54:21 -0000 1.21 --- src/template/unixware 13 Sep 2003 14:47:47 -0000 *************** *** 10,14 **** fi SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNC_NAMES=no # verified 7.1.3 2003-09-03 THREAD_CFLAGS="$THREAD_CFLAGS -D_REENTRANT" --- 10,14 ---- fi SUPPORTS_THREADS=yes ! NEED_REENTRANT_FUNCS=no # verified 7.1.3 2003-09-03 THREAD_CFLAGS="$THREAD_CFLAGS -D_REENTRANT"