Improved fix for sys_nerr - Mailing list pgsql-patches

From Pete Forman
Subject Improved fix for sys_nerr
Date
Msg-id 14839.63627.58567.35604@kryten.bedford.waii.com
Whole thread Raw
Responses Re: Improved fix for sys_nerr  (Tom Lane <tgl@sss.pgh.pa.us>)
List pgsql-patches
============================================================================
                        POSTGRESQL BUG REPORT TEMPLATE
============================================================================


Your name        :    Pete Forman
Your email address    :       pete.forman@westgeo.com


System Configuration
---------------------
  Architecture (example: Intel Pentium)      : Intel Pentium II

  Operating System (example: Linux 2.0.26 ELF)     : Cygwin B20.1 and others

  PostgreSQL version (example: PostgreSQL-7.1):   PostgreSQL-7.1

  Compiler used (example:  gcc 2.8.0)        : egcs-2.91.57


Please enter a FULL description of your problem:
------------------------------------------------

Files backend/utils/error/elog.c and exc.c had errors building on
Cygwin B20.1 (and BeOS so I'm told).  The current source (elog.c,v
1.64, exc.c,v 1.31) is fixed for Cygwin 1.1 and BeOS but not very
robustly.  This patch works on the systems and versions I've tested.
Others were tested by subscribers to PORTS.

The changes made are:

   1) Remove declarations of "extern int errno;".
      - errno does not have to be an int, it may be a macro.  In
        threaded code it almost certainly will be the latter.
        <errno.h> will already have the correct declaration.

   2) Remove sys_nerr and _sys_nerr.
      - These are not portable, e.g. older Cygwin and BeOS.
        In any case the test errno < sys_nerr assumes that valid
        errnos are contiguous.  strerror() may go wrong on holes.

   3) Test both errno and the return of strerror() to see if it fails.
      - This works an all(?) OSs except HPUX and QNX.  These then have
        a minor limitation that if the elog() is called with an out of
        range errno then its number will not be printed.  I would
        expect that it would be called with a valid errno.
        In exc.c both the errno and its message, if available, are now
        printed.
        I leave it to the user to call elog(..., "%d: %m", errno, ...)
        if they want to guarantee a number.
        Anything more complicated will need to involve configure.  I
        am loathe to do so because this sort of error code is called
        infrequently and will only be tested lightly.  Keep it
        simple.

    4) Remove any OS specific clauses: ifdef __CYGWIN__ or __BEOS__.



I have posted an equivalent patch to PORTS for 7.0.2.


Please describe a way to repeat the problem.   Please try to provide a
concise reproducible example, if at all possible:
----------------------------------------------------------------------





If you know how this problem might be fixed, list the solution below:
---------------------------------------------------------------------

*** src/backend/utils/error/elog.c.orig    Sun Oct  8 08:00:18 2000
--- src/backend/utils/error/elog.c    Wed Oct 25 16:55:50 2000
***************
*** 37,49 ****
  #include "tcop/tcopprot.h"
  #include "commands/copy.h"

- extern int    errno;
-
- #ifdef __CYGWIN__
- # define sys_nerr _sys_nerr
- #endif
- extern int    sys_nerr;
-
  extern CommandDest whereToSendOutput;

  #ifdef ENABLE_SYSLOG
--- 37,42 ----
***************
*** 130,152 ****
      int            len;
      /* size of the prefix needed for timestamp and pid, if enabled */
      size_t      timestamp_size;

      if (lev <= DEBUG && Debugfile < 0)
          return;                    /* ignore debug msgs if noplace to send */

! /* BeOS doesn't have sys_nerr and should be able to use strerror()... */
! #ifndef __BEOS__
!     /* save errno string for %m */
!     if (errno < sys_nerr && errno >= 0)
!         errorstr = strerror(errno);
!     else
      {
!         sprintf(errorstr_buf, "error %d", errno);
          errorstr = errorstr_buf;
      }
- #else
-     errorstr = strerror(errno);
- #endif /* __BEOS__ */

      if (lev == ERROR || lev == FATAL)
      {
--- 123,151 ----
      int            len;
      /* size of the prefix needed for timestamp and pid, if enabled */
      size_t      timestamp_size;
+     int            errno_copy = errno;

      if (lev <= DEBUG && Debugfile < 0)
          return;                    /* ignore debug msgs if noplace to send */

!     /*
!      * save errno string for %m
!      * Standard UNIX (XPG4v2/UNIX95 and later) says that errno will be set
!      * (to EINVAL) if the argument to strerror() is out of range.
!      * IRIX and Solaris actually return NULL without setting errno.
!      * Others such as AIX, Cygwin and Linux return a string for all values.
!      *   This string contains a number for out of range values.
!      * HPUX and QNX return the same string for all out of range values.
!      *   Those will not be well served by this code.  However it is highly
!      *   unlikely that this code will be called with an out of range errno.
!      */
!     errno = 0;
!     errorstr = strerror(errno_copy);
!     if (errno != 0 || errorstr == NULL)
      {
!         sprintf(errorstr_buf, "error %d", errno_copy);
          errorstr = errorstr_buf;
      }

      if (lev == ERROR || lev == FATAL)
      {
*** src/backend/utils/error/exc.c.orig    Tue Oct  3 08:00:18 2000
--- src/backend/utils/error/exc.c    Wed Oct 25 16:37:39 2000
***************
*** 94,106 ****
      ExceptionHandlingEnabled = on;
  }

-
- extern int    errno;
- #ifdef __CYGWIN__
- # define sys_nerr _sys_nerr
- #endif
- extern int    sys_nerr;
-
  static void
  ExcPrint(Exception *excP,
           ExcDetail detail,
--- 94,99 ----
***************
*** 107,112 ****
--- 100,108 ----
           ExcData data,
           ExcMessage message)
  {
+     int errno_copy = errno;
+     const char *errorstr;
+
  #ifdef    lint
      data = data;
  #endif
***************
*** 131,144 ****

      fprintf(stderr, " (%ld)", detail);

! #ifndef __BEOS__
!     if (errno > 0 && errno < sys_nerr)
! #else
!     if (errno > 0)
! #endif
!         fprintf(stderr, " [%s]", strerror(errno));
!     else if (errno != 0)
!         fprintf(stderr, " [Error %d]", errno);

      fprintf(stderr, "\n");

--- 127,140 ----

      fprintf(stderr, " (%ld)", detail);

!     if (errno_copy != 0) {
!         errno = 0;
!         errorstr = strerror(errno_copy);
!         if (errno == 0 && errorstr != NULL)
!             fprintf(stderr, " [Error %d: %s]", errno_copy, errorstr);
!         else if (errno_copy != 0)
!             fprintf(stderr, " [Error %d]", errno_copy);
!     }

      fprintf(stderr, "\n");



--
Pete Forman                 -./\.- Disclaimer: This post is originated
Western Geophysical           -./\.-  by myself and does not represent
pete.forman@westgeo.com         -./\.-  the opinion of Baker Hughes or
http://www.crosswinds.net/~petef  -./\.-  its divisions.

pgsql-patches by date:

Previous
From: Bruce Momjian
Date:
Subject: Re: minor doc patchu
Next
From: Peter Eisentraut
Date:
Subject: Re: readline and openbsd