Re: Unixware Patch (Was: Re: Beta2 Tag'd and Bundled ...)

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: Unixware Patch (Was: Re: Beta2 Tag'd and Bundled ...)
Дата
Msg-id 200309131448.h8DEma228745@candle.pha.pa.us
обсуждение исходный текст
Ответ на Re: Unixware Patch (Was: Re: Beta2 Tag'd and Bundled ...)  (Bruce Momjian <pgman@candle.pha.pa.us>)
Список pgsql-hackers
[ I have retained the original email below so people can remember where
we left this.]

After much agonizing, I have applied a patch to attempt 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

With Solaris, FreeBSD, and OSF failing our existing setup, the last
option of doing our own locking and copying seemed necessary.  The good
news is that this is used only if another method can not be found.  I
used the 'bind' source code as an example of how to do this.

Patch sent to patches list.

---------------------------------------------------------------------------

Bruce Momjian wrote:
> Philip Yarra wrote:
> > On Thu, 4 Sep 2003 05:36 am, Bruce Momjian wrote:
> > > I would like every operating system that supports thread-safety to run
> > > this program and report back the results.
> >
> > Okay, here's results from the machines I have access to... I think what you're
> > going to find is that an awful lot of platforms that do support pthreads do
> > not necessarily provide thread-safe libc functions.
>
> I see --- looks bad ---- failures below for OSF, Solaris, and FreeBSD
> below.
>
> > Is it possible to identify which functions are likely to be called by multiple
> > threads and create our own mutex-wrapper functions for them? Disabling
> > thread-safety seems pretty drastic simply because of a lack of getpwuid_r()
> > or thread-safe getpwuid(). Or do I misunderstand your concerns?
>
> I am starting to think your approach is the only way to go --- I was
> thinking of it for FreeBSD, but now, with these additional platforms, it
> seems almost a requirement.
>
> We would have to get some thread mutex, make the function call, copy the
> return values into the passed pointer, and release the mutex?  Do we
> test to see if we are in thread mode before doing the locking?  Is that
> test even possible or desirable?
>
> Seems we will need to rename the config variable to be
> NON_REENTRANT_FUNC_NAMES_THREADSAFE, and add configure checks for each
> *_r function, and fall back to the mutex if both settings are false.
>
> This part has me concerned too:
>
> > Copying the struct hostent does not suffice, since it contains
> > pointers  -  a  deep copy is required.
>
> Would someone with thread mutex experience assist me?
>
>
> ---------------------------------------------------------------------------
>
> >
> > Regards, Philip.
> >
> > $ uname -a
> > OSF1 hostname V4.0 1229 alpha
> > $ ./a.out
> > Your getpwuid() changes the static memory area between calls
> > Your strerror() is _not_ thread-safe
> > Your functions are _not_ all thread-safe
> >
> > There are older _r functions, but they're deprecated as the non _r are now
> > thread-safe.
> >
> > $ uname -a
> > SunOS hostname 5.6 Generic_105181-05 sun4m sparc SUNW,SPARCstation-4
> > $ gcc -lpthread -lnsl test.c # this works
> > $ ./a.out
> > Your gethostbyname() is _not_ thread-safe
> > Your getpwuid() is _not_ thread-safe
> > Your functions are _not_ all thread-safe
> >
> > getpwduid_r provided
> > gethostbyname_r not provided
> >
> > FreeBSD 5.1 (i386)
> > $ cc -pthread test.c
> > $ ./a.out
> > Your gethostbyname() is _not_ thread-safe
> > Your getpwuid() is _not_ thread-safe
> > Your functions are _not_ all thread-safe
> >
> > manpage notes "BUGS
> >      These functions use static data storage; if the data is needed for future
> >      use, it should be copied before any subsequent calls overwrite it."
> >
> > FreeBSD 4.8 (i386)
> > $ cc -pthread test.c
> > $ ./a.out
> > Your gethostbyname() is _not_ thread-safe
> > Your getpwuid() is _not_ thread-safe
> > Your functions are _not_ all thread-safe
> >
> > manpage notes "BUGS
> >      These functions use static data storage; if the data is needed for future
> >      use, it should be copied before any subsequent calls overwrite it."
> >
> > Linux 2.4.18-3 (i686)
> > $ ./a.out
> > Your gethostbyname() is _not_ thread-safe
> > Your getpwuid() is _not_ thread-safe
> > Your functions are _not_ all thread-safe
> >
> > manpage notes "The  functions  gethostbyname()  and gethostbyaddr() may return
> > pointers to static data, which may be over-
> >        written by later calls. Copying the struct hostent does not suffice,
> > since it contains pointers  -  a  deep
> >        copy is required.
> >
> > Glibc2 also has reentrant versions gethostbyname_r() and gethostbyname2_r().
> > These return 0 on success and
> >        nonzero  on  error.  The  result of the call is now stored in the
> > struct with address ret.  After the call,
> >        *result will be NULL on error or point to the result on success.
> > Auxiliary data is stored  in  the  buffer
> >        buf  of  length buflen.  (If the buffer is too small, these functions
> > will return ERANGE.)  No global vari-
> >        able h_errno is modified, but the address of a variable in which  to
> > store  error  numbers  is  passed  in
> >        h_errnop."
> >
>
> --
>   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
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
>

--
  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.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 <pthread.h>
+ #include <sys/types.h>
+ #include <pwd.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. 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"

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Ang Chin Han
Дата:
Сообщение: Re: massive quotes?
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: Another small bug (pg_autovacuum)