Here is a new file, threads.c, which implements the functions needed for
libpq threading.
One tricky part was to add the threading flags to the compile of just
thread.c. I used:
# compile this with thread flags
thread.o: thread.c
$(CC) $(CFLAGS) $(THREAD_CFLAGS) -c thread.c
I assume that is the correct way to do it.
--
Bruce Momjian | http://candle.pha.pa.us
pgman@candle.pha.pa.us | (610) 359-1001
+ If your life is a hard drive, | 13 Roberts Road
+ Christ can be your backup. | Newtown Square, Pennsylvania 19073
Index: configure
===================================================================
RCS file: /cvsroot/pgsql-server/configure,v
retrieving revision 1.270
diff -c -c -r1.270 configure
*** configure 13 Jun 2003 23:10:04 -0000 1.270
--- configure 14 Jun 2003 14:12:34 -0000
***************
*** 2824,2830 ****
case $withval in
yes)
! :
;;
no)
:
--- 2824,2834 ----
case $withval in
yes)
!
! cat >>confdefs.h <<\_ACEOF
! #define USE_THREADS 1
! _ACEOF
!
;;
no)
:
***************
*** 2841,2846 ****
--- 2845,2851 ----
fi;
+
echo "$as_me:$LINENO: result: $with_threads" >&5
echo "${ECHO_T}$with_threads" >&6
***************
*** 3899,3907 ****
# these require no special flags or libraries
;;
freebsd2*|freebsd3*|freebsd4*) THREAD_CFLAGS="-pthread" ;;
! freebsd*) THREAD_LIBS="-lc_r" ;;
! linux*) THREAD_LIBS="-lpthread"
! THREAD_CFLAGS="-D_REENTRANT" ;;
*)
# other operating systems might fail because they have pthread.h but need
# special libs we don't know about yet.
--- 3904,3915 ----
# these require no special flags or libraries
;;
freebsd2*|freebsd3*|freebsd4*) THREAD_CFLAGS="-pthread" ;;
! freebsd*)
! THREAD_LIBS="-lc_r"
! ;;
! linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
! THREAD_LIBS="-lpthread"
! ;;
*)
# other operating systems might fail because they have pthread.h but need
# special libs we don't know about yet.
***************
*** 3918,3924 ****
or libraries required for threading support.
" >&2;}
{ (exit 1); exit 1; }; }
! esac
fi
--- 3926,3932 ----
or libraries required for threading support.
" >&2;}
{ (exit 1); exit 1; }; }
! esac
fi
***************
*** 12818,12823 ****
--- 12826,12922 ----
fi
+ #
+ # Check for re-entrant versions of certain functions
+ #
+ # Include special flags if required
+ #
+ _CFLAGS="$CFLAGS"
+ _LIB="$LIBS"
+ CFLAGS="$CFLAGS $TREAD_CFLAGS"
+ LIBS="$LIBS $THREAD_LIBS"
+
+
+
+ for ac_func in strerror_r getpwuid_r gethostbyname_r
+ do
+ as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ echo "$as_me:$LINENO: checking for $ac_func" >&5
+ echo $ECHO_N "checking for $ac_func... $ECHO_C" >&6
+ if eval "test \"\${$as_ac_var+set}\" = set"; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ /* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $ac_func (); below. */
+ #include <assert.h>
+ /* Override any gcc2 internal prototype to avoid an error. */
+ #ifdef __cplusplus
+ extern "C"
+ #endif
+ /* We use char because int might match the return type of a gcc2
+ builtin and then its argument prototype would still apply. */
+ char $ac_func ();
+ char (*f) ();
+
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ /* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+ #if defined (__stub_$ac_func) || defined (__stub___$ac_func)
+ choke me
+ #else
+ f = $ac_func;
+ #endif
+
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+ (eval $ac_link) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest$ac_exeext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ eval "$as_ac_var=yes"
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ eval "$as_ac_var=no"
+ fi
+ rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_var'}'`" >&5
+ echo "${ECHO_T}`eval echo '${'$as_ac_var'}'`" >&6
+ if test `eval echo '${'$as_ac_var'}'` = yes; then
+ cat >>confdefs.h <<_ACEOF
+ #define `echo "HAVE_$ac_func" | $as_tr_cpp` 1
+ _ACEOF
+
+ fi
+ done
+
+ CFLAGS="$_CFLAGS"
+ LIB="$_LIBS"
+
+
# This test makes sure that run tests work at all. Sometimes a shared
# library is found by the linker, but the runtime linker can't find it.
***************
*** 17603,17610 ****
s,@with_rendezvous@,$with_rendezvous,;t t
s,@with_openssl@,$with_openssl,;t t
s,@ELF_SYS@,$ELF_SYS,;t t
- s,@THREAD_LIBS@,$THREAD_LIBS,;t t
s,@THREAD_CFLAGS@,$THREAD_CFLAGS,;t t
s,@AWK@,$AWK,;t t
s,@FLEX@,$FLEX,;t t
s,@FLEXFLAGS@,$FLEXFLAGS,;t t
--- 17702,17709 ----
s,@with_rendezvous@,$with_rendezvous,;t t
s,@with_openssl@,$with_openssl,;t t
s,@ELF_SYS@,$ELF_SYS,;t t
s,@THREAD_CFLAGS@,$THREAD_CFLAGS,;t t
+ s,@THREAD_LIBS@,$THREAD_LIBS,;t t
s,@AWK@,$AWK,;t t
s,@FLEX@,$FLEX,;t t
s,@FLEXFLAGS@,$FLEXFLAGS,;t t
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql-server/configure.in,v
retrieving revision 1.261
diff -c -c -r1.261 configure.in
*** configure.in 13 Jun 2003 23:10:07 -0000 1.261
--- configure.in 14 Jun 2003 14:12:36 -0000
***************
*** 323,329 ****
# Enable libpq to be thread-safe
#
AC_MSG_CHECKING([allow threaded libpq])
! PGAC_ARG_BOOL(with, threads, no, [ --with-threads allow libpq to be thread-safe])
AC_MSG_RESULT([$with_threads])
AC_SUBST(with_threads)
--- 323,331 ----
# Enable libpq to be thread-safe
#
AC_MSG_CHECKING([allow threaded libpq])
! PGAC_ARG_BOOL(with, threads, no, [ --with-threads allow libpq to be thread-safe],
! [AC_DEFINE([USE_THREADS], 1, [Define to 1 to build libpq with threads. (--with-threads)])])
!
AC_MSG_RESULT([$with_threads])
AC_SUBST(with_threads)
***************
*** 559,567 ****
# these require no special flags or libraries
;;
freebsd2*|freebsd3*|freebsd4*) THREAD_CFLAGS="-pthread" ;;
! freebsd*) THREAD_LIBS="-lc_r" ;;
! linux*) THREAD_LIBS="-lpthread"
! THREAD_CFLAGS="-D_REENTRANT" ;;
*)
# other operating systems might fail because they have pthread.h but need
# special libs we don't know about yet.
--- 561,572 ----
# these require no special flags or libraries
;;
freebsd2*|freebsd3*|freebsd4*) THREAD_CFLAGS="-pthread" ;;
! freebsd*)
! THREAD_LIBS="-lc_r"
! ;;
! linux*) THREAD_CFLAGS="-D_REENTRANT -D_THREAD_SAFE -D_POSIX_PTHREAD_SEMANTICS"
! THREAD_LIBS="-lpthread"
! ;;
*)
# other operating systems might fail because they have pthread.h but need
# special libs we don't know about yet.
***************
*** 571,580 ****
so it can be added to the next release. Report any compile or link flags,
or libraries required for threading support.
])
! esac
fi
- AC_SUBST(THREAD_LIBS)
AC_SUBST(THREAD_CFLAGS)
#
# Assignments
--- 576,585 ----
so it can be added to the next release. Report any compile or link flags,
or libraries required for threading support.
])
! esac
fi
AC_SUBST(THREAD_CFLAGS)
+ AC_SUBST(THREAD_LIBS)
#
# Assignments
***************
*** 982,987 ****
--- 987,1006 ----
[AC_MSG_ERROR([neither atexit() nor on_exit() found])])])
AC_FUNC_FSEEKO
+
+ #
+ # Check for re-entrant versions of certain functions
+ #
+ # Include special flags if required
+ #
+ _CFLAGS="$CFLAGS"
+ _LIB="$LIBS"
+ CFLAGS="$CFLAGS $TREAD_CFLAGS"
+ LIBS="$LIBS $THREAD_LIBS"
+ AC_CHECK_FUNCS([strerror_r getpwuid_r gethostbyname_r])
+ CFLAGS="$_CFLAGS"
+ LIB="$_LIBS"
+
# This test makes sure that run tests work at all. Sometimes a shared
Index: src/Makefile.global.in
===================================================================
RCS file: /cvsroot/pgsql-server/src/Makefile.global.in,v
retrieving revision 1.163
diff -c -c -r1.163 Makefile.global.in
*** src/Makefile.global.in 27 May 2003 16:36:50 -0000 1.163
--- src/Makefile.global.in 14 Jun 2003 14:12:43 -0000
***************
*** 121,126 ****
--- 121,127 ----
#
# Records the choice of the various --enable-xxx and --with-xxx options.
+ with_threads = @with_threads@
with_java = @with_java@
with_perl = @with_perl@
with_python = @with_python@
***************
*** 340,346 ****
#
# substitute implementations of the C library
! LIBOBJS = @LIBOBJS@ path.o
ifneq (,$(LIBOBJS))
LIBS += -lpgport
--- 341,347 ----
#
# substitute implementations of the C library
! LIBOBJS = @LIBOBJS@ path.o threads.o
ifneq (,$(LIBOBJS))
LIBS += -lpgport
Index: src/include/pg_config.h.in
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/pg_config.h.in,v
retrieving revision 1.51
diff -c -c -r1.51 pg_config.h.in
*** src/include/pg_config.h.in 13 Jun 2003 23:10:08 -0000 1.51
--- src/include/pg_config.h.in 14 Jun 2003 14:12:45 -0000
***************
*** 121,126 ****
--- 121,129 ----
/* Define to 1 if you have the `getaddrinfo' function. */
#undef HAVE_GETADDRINFO
+ /* Define to 1 if you have the `gethostbyname_r' function. */
+ #undef HAVE_GETHOSTBYNAME_R
+
/* Define to 1 if you have the `gethostname' function. */
#undef HAVE_GETHOSTNAME
***************
*** 136,141 ****
--- 139,147 ----
/* Define to 1 if you have the `getpeereid' function. */
#undef HAVE_GETPEEREID
+ /* Define to 1 if you have the `getpwuid_r' function. */
+ #undef HAVE_GETPWUID_R
+
/* Define to 1 if you have the `getrusage' function. */
#undef HAVE_GETRUSAGE
***************
*** 375,380 ****
--- 381,389 ----
/* Define to 1 if you have the `strerror' function. */
#undef HAVE_STRERROR
+ /* Define to 1 if you have the `strerror_r' function. */
+ #undef HAVE_STRERROR_R
+
/* Define to 1 if cpp supports the ANSI # stringizing operator. */
#undef HAVE_STRINGIZE
***************
*** 578,583 ****
--- 587,595 ----
/* Define to select SysV-style shared memory. */
#undef USE_SYSV_SHARED_MEMORY
+
+ /* Define to 1 to build libpq with threads. (--with-threads) */
+ #undef USE_THREADS
/* Define to select unnamed POSIX semaphores. */
#undef USE_UNNAMED_POSIX_SEMAPHORES
Index: src/include/port.h
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/port.h,v
retrieving revision 1.6
diff -c -c -r1.6 port.h
*** src/include/port.h 12 Jun 2003 08:15:29 -0000 1.6
--- src/include/port.h 14 Jun 2003 14:12:45 -0000
***************
*** 11,16 ****
--- 11,20 ----
*-------------------------------------------------------------------------
*/
+ /* for thread.c */
+ #include <pwd.h>
+ #include <netdb.h>
+
/* Portable path handling for Unix/Win32 */
bool is_absolute_path(const char *filename);
char *first_path_separator(const char *filename);
***************
*** 98,100 ****
--- 102,116 ----
#ifndef HAVE_SRANDOM
extern void srandom(unsigned int seed);
#endif
+
+ /* thread.h */
+ extern char *pqStrerror(int errnum, char *strerrbuf, size_t buflen);
+
+ extern int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
+ size_t buflen, struct passwd **result);
+
+ extern int pqGethostbyname(const char *name,
+ struct hostent *resbuf,
+ char *buf, size_t buflen,
+ struct hostent **result,
+ int *herrno);
Index: src/interfaces/libpq/Makefile
===================================================================
RCS file: /cvsroot/pgsql-server/src/interfaces/libpq/Makefile,v
retrieving revision 1.81
diff -c -c -r1.81 Makefile
*** src/interfaces/libpq/Makefile 12 Jun 2003 17:31:50 -0000 1.81
--- src/interfaces/libpq/Makefile 14 Jun 2003 14:12:46 -0000
***************
*** 23,29 ****
OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \
dllist.o md5.o ip.o wchar.o encnames.o \
! $(filter crypt.o getaddrinfo.o inet_aton.o snprintf.o strerror.o path.o, $(LIBOBJS))
# Add libraries that libpq depends (or might depend) on into the
--- 23,29 ----
OBJS= fe-auth.o fe-connect.o fe-exec.o fe-misc.o fe-print.o fe-lobj.o \
fe-protocol2.o fe-protocol3.o pqexpbuffer.o pqsignal.o fe-secure.o \
dllist.o md5.o ip.o wchar.o encnames.o \
! $(filter crypt.o getaddrinfo.o inet_aton.o snprintf.o strerror.o path.o threads.o, $(LIBOBJS))
# Add libraries that libpq depends (or might depend) on into the
***************
*** 46,53 ****
# For port modules, this only happens if configure decides the module
# is needed (see filter hack in OBJS, above).
! crypt.c getaddrinfo.c inet_aton.c snprintf.c strerror.c path.c: %.c : $(top_srcdir)/src/port/%.c
rm -f $@ && $(LN_S) $< .
dllist.c: $(backend_src)/lib/dllist.c
rm -f $@ && $(LN_S) $< .
--- 46,57 ----
# For port modules, this only happens if configure decides the module
# is needed (see filter hack in OBJS, above).
! crypt.c getaddrinfo.c inet_aton.c snprintf.c strerror.c path.c threads.c: %.c : $(top_srcdir)/src/port/%.c
rm -f $@ && $(LN_S) $< .
+
+ # compile this with thread flags
+ thread.o: thread.c
+ $(CC) $(CFLAGS) $(THREAD_CFLAGS) -c thread.c
dllist.c: $(backend_src)/lib/dllist.c
rm -f $@ && $(LN_S) $< .
Index: src/port/Makefile
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/Makefile,v
retrieving revision 1.3
diff -c -c -r1.3 Makefile
*** src/port/Makefile 27 Jul 2002 20:10:05 -0000 1.3
--- src/port/Makefile 14 Jun 2003 14:12:47 -0000
***************
*** 22,26 ****
--- 22,29 ----
libpgport.a: $(LIBOBJS)
$(AR) crs $@ $^
+ thread.o: thread.c
+ $(CC) $(CFLAGS) $(THREAD_CFLAGS) -c thread.c
+
clean distclean maintainer-clean:
rm -f libpgport.a $(LIBOBJS)
/*-------------------------------------------------------------------------
*
* threads.c
*
* Prototypes and macros around system calls, used to help make
* threaded libraries reentrant and safe to use from threaded applications.
*
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
*
* $Id:$
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
/*
* Wrapper around strerror and strerror_r to use the former if it is
* available and also return a more useful value (the error string).
*/
char *
pqStrerror(int errnum, char *strerrbuf, size_t buflen)
{
#if defined(USE_THREADS) && 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
/* no strerror_r() available, just use strerror */
return strerror(errnum);
#endif
}
/*
* Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
* behaviour, if it is not available.
*/
int
pqGetpwuid(uid_t uid, struct passwd * resultbuf, char *buffer,
size_t buflen, struct passwd ** result)
{
#if defined(USE_THREADS) && defined(HAVE_GETPWUID_R)
/*
* broken (well early POSIX draft) getpwuid_r() which returns 'struct
* passwd *'
*/
*result = getpwuid_r(uid, resultbuf, buffer, buflen);
#else
/* no getpwuid_r() available, just use getpwuid() */
*result = getpwuid(uid);
#endif
return (*result == NULL) ? -1 : 0;
}
/*
* Wrapper around gethostbyname() or gethostbyname_r() to mimic
* POSIX gethostbyname_r() behaviour, if it is not available.
*/
int
pqGethostbyname(const char *name,
struct hostent * resbuf,
char *buf, size_t buflen,
struct hostent ** result,
int *herrno)
{
#if defined(USE_THREADS) && defined(HAVE_GETHOSTBYNAME_R)
/*
* 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
}