This patch fixes strerror_r() by checking the return type from
configure.
---------------------------------------------------------------------------
Tom Lane wrote:
> Bruce Momjian <pgman@candle.pha.pa.us> writes:
> >> The code we have appears to assume that the result will always be placed
> >> in the user-supplied buffer, which is apparently NOT what the glibc
> >> version does.
>
> > What does "may, but need not, use the user-supplied buffer" supposed to
> > mean in practical terms. How do they expect us to use it?
>
> AFAICS they expect you to use the function's return value.
>
> The current PG code is really erroneous for *both* strerror_r specs,
> since the SUS-spec version doesn't promise to put anything into the
> buffer if it returns a failure code. I think you will have to write
> some autoconf code to detect which return type is provided, and do
> the right things with the return value in both cases.
>
> regards, tom lane
>
--
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.371
diff -c -c -r1.371 configure
*** configure 28 May 2004 20:52:41 -0000 1.371
--- configure 7 Jun 2004 22:21:45 -0000
***************
*** 13759,13764 ****
--- 13759,13817 ----
fi
+ echo "$as_me:$LINENO: checking whether strerror_r returns int" >&5
+ echo $ECHO_N "checking whether strerror_r returns int... $ECHO_C" >&6
+ if test "${pgac_func_strerror_r_int+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+ else
+ cat >conftest.$ac_ext <<_ACEOF
+ #line $LINENO "configure"
+ #include "confdefs.h"
+ #include <string.h>
+ #ifdef F77_DUMMY_MAIN
+ # ifdef __cplusplus
+ extern "C"
+ # endif
+ int F77_DUMMY_MAIN() { return 1; }
+ #endif
+ int
+ main ()
+ {
+ int strerror_r(int, char *, size_t);
+ ;
+ return 0;
+ }
+ _ACEOF
+ rm -f conftest.$ac_objext
+ if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (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
+ pgac_func_strerror_r_int=yes
+ else
+ echo "$as_me: failed program was:" >&5
+ cat conftest.$ac_ext >&5
+ pgac_func_strerror_r_int=no
+ fi
+ rm -f conftest.$ac_objext conftest.$ac_ext
+ fi
+ echo "$as_me:$LINENO: result: $pgac_func_strerror_r_int" >&5
+ echo "${ECHO_T}$pgac_func_strerror_r_int" >&6
+ if test x"$pgac_func_strerror_r_int" = xyes ; then
+
+ cat >>confdefs.h <<\_ACEOF
+ #define STRERROR_R_INT
+ _ACEOF
+
+ fi
+
else
# do not use values from template file
Index: configure.in
===================================================================
RCS file: /cvsroot/pgsql-server/configure.in,v
retrieving revision 1.360
diff -c -c -r1.360 configure.in
*** configure.in 28 May 2004 20:52:42 -0000 1.360
--- configure.in 7 Jun 2004 22:21:53 -0000
***************
*** 993,998 ****
--- 993,999 ----
LIBS="$_LIBS"
PGAC_FUNC_GETPWUID_R_5ARG
+ PGAC_FUNC_STRERROR_R_INT
else
# do not use values from template file
Index: config/c-library.m4
===================================================================
RCS file: /cvsroot/pgsql-server/config/c-library.m4,v
retrieving revision 1.25
diff -c -c -r1.25 c-library.m4
*** config/c-library.m4 20 Mar 2004 15:39:27 -0000 1.25
--- config/c-library.m4 7 Jun 2004 22:21:53 -0000
***************
*** 96,101 ****
--- 96,118 ----
])# PGAC_FUNC_GETPWUID_R_5ARG
+ # PGAC_FUNC_STRERROR_R_INT
+ # ---------------------------
+ # Check if strerror_r() returns an int (SUSv3) rather than a char * (GNU libc)
+ # If so, define STRERROR_R_INT
+ AC_DEFUN([PGAC_FUNC_STRERROR_R_INT],
+ [AC_CACHE_CHECK(whether strerror_r returns int,
+ pgac_func_strerror_r_int,
+ [AC_TRY_COMPILE([#include <string.h>],
+ [int strerror_r(int, char *, size_t);],
+ [pgac_func_strerror_r_int=yes],
+ [pgac_func_strerror_r_int=no])])
+ if test x"$pgac_func_strerror_r_int" = xyes ; then
+ AC_DEFINE(STRERROR_R_INT,, [Define to 1 if strerror_r() returns a int.])
+ fi
+ ])# PGAC_FUNC_STRERROR_R_INT
+
+
# PGAC_UNION_SEMUN
# ----------------
# Check if `union semun' exists. Define HAVE_UNION_SEMUN if so.
Index: src/include/pg_config.h.in
===================================================================
RCS file: /cvsroot/pgsql-server/src/include/pg_config.h.in,v
retrieving revision 1.76
diff -c -c -r1.76 pg_config.h.in
*** src/include/pg_config.h.in 22 May 2004 00:34:51 -0000 1.76
--- src/include/pg_config.h.in 7 Jun 2004 22:21:56 -0000
***************
*** 607,612 ****
--- 607,615 ----
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
+ /* Define to 1 if strerror_r() returns a int. */
+ #undef STRERROR_R_INT
+
/* Define to 1 if your <sys/time.h> declares `struct tm'. */
#undef TM_IN_SYS_TIME
Index: src/port/thread.c
===================================================================
RCS file: /cvsroot/pgsql-server/src/port/thread.c,v
retrieving revision 1.20
diff -c -c -r1.20 thread.c
*** src/port/thread.c 23 Apr 2004 18:15:55 -0000 1.20
--- src/port/thread.c 7 Jun 2004 22:21:56 -0000
***************
*** 70,81 ****
{
#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && 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 */
StrNCpy(strerrbuf, strerror(errnum), buflen);
--- 70,86 ----
{
#if defined(FRONTEND) && defined(ENABLE_THREAD_SAFETY) && defined(HAVE_STRERROR_R)
/* reentrant strerror_r is available */
! #ifdef STRERROR_R_INT
! /* SUSv3 version */
! if (strerror_r(errnum, strerrbuf, buflen) == 0)
! return strerrbuf;
! else
! return NULL;
! #else
! /* GNU libc */
! return strerror_r(errnum, strerrbuf, buflen);
! #endif
#else
/* no strerror_r() available, just use strerror */
StrNCpy(strerrbuf, strerror(errnum), buflen);