Skip to content

Commit 8cfd4c6

Browse files
committed
Be more robust when strerror() doesn't give a useful result.
Back-patch commits 8e68816 and 8dace66 into the stable branches. Buildfarm testing revealed no great portability surprises, and it seems useful to have this robustness improvement in all branches.
1 parent 6e2c762 commit 8cfd4c6

File tree

1 file changed

+183
-4
lines changed

1 file changed

+183
-4
lines changed

src/backend/utils/error/elog.c

Lines changed: 183 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ static void send_message_to_server_log(ErrorData *edata);
160160
static void send_message_to_frontend(ErrorData *edata);
161161
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
162162
static const char *useful_strerror(int errnum);
163+
static const char *get_errno_symbol(int errnum);
163164
static const char *error_severity(int elevel);
164165
static void append_with_tabs(StringInfo buf, const char *str);
165166
static bool is_log_level_output(int elevel, int log_min_level);
@@ -2748,7 +2749,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
27482749
static const char *
27492750
useful_strerror(int errnum)
27502751
{
2751-
/* this buffer is only used if errno has a bogus value */
2752+
/* this buffer is only used if strerror() and get_errno_symbol() fail */
27522753
static char errorstr_buf[48];
27532754
const char *str;
27542755

@@ -2760,10 +2761,16 @@ useful_strerror(int errnum)
27602761
str = strerror(errnum);
27612762

27622763
/*
2763-
* Some strerror()s return an empty string for out-of-range errno. This is
2764-
* ANSI C spec compliant, but not exactly useful.
2764+
* Some strerror()s return an empty string for out-of-range errno. This
2765+
* is ANSI C spec compliant, but not exactly useful. Also, we may get
2766+
* back strings of question marks if libc cannot transcode the message to
2767+
* the codeset specified by LC_CTYPE. If we get nothing useful, first try
2768+
* get_errno_symbol(), and if that fails, print the numeric errno.
27652769
*/
2766-
if (str == NULL || *str == '\0')
2770+
if (str == NULL || *str == '\0' || *str == '?')
2771+
str = get_errno_symbol(errnum);
2772+
2773+
if (str == NULL)
27672774
{
27682775
snprintf(errorstr_buf, sizeof(errorstr_buf),
27692776
/*------
@@ -2776,6 +2783,178 @@ useful_strerror(int errnum)
27762783
return str;
27772784
}
27782785

2786+
/*
2787+
* Returns a symbol (e.g. "ENOENT") for an errno code.
2788+
* Returns NULL if the code is unrecognized.
2789+
*/
2790+
static const char *
2791+
get_errno_symbol(int errnum)
2792+
{
2793+
switch (errnum)
2794+
{
2795+
case E2BIG:
2796+
return "E2BIG";
2797+
case EACCES:
2798+
return "EACCES";
2799+
#ifdef EADDRINUSE
2800+
case EADDRINUSE:
2801+
return "EADDRINUSE";
2802+
#endif
2803+
#ifdef EADDRNOTAVAIL
2804+
case EADDRNOTAVAIL:
2805+
return "EADDRNOTAVAIL";
2806+
#endif
2807+
case EAFNOSUPPORT:
2808+
return "EAFNOSUPPORT";
2809+
#ifdef EAGAIN
2810+
case EAGAIN:
2811+
return "EAGAIN";
2812+
#endif
2813+
#ifdef EALREADY
2814+
case EALREADY:
2815+
return "EALREADY";
2816+
#endif
2817+
case EBADF:
2818+
return "EBADF";
2819+
#ifdef EBADMSG
2820+
case EBADMSG:
2821+
return "EBADMSG";
2822+
#endif
2823+
case EBUSY:
2824+
return "EBUSY";
2825+
case ECHILD:
2826+
return "ECHILD";
2827+
#ifdef ECONNABORTED
2828+
case ECONNABORTED:
2829+
return "ECONNABORTED";
2830+
#endif
2831+
case ECONNREFUSED:
2832+
return "ECONNREFUSED";
2833+
#ifdef ECONNRESET
2834+
case ECONNRESET:
2835+
return "ECONNRESET";
2836+
#endif
2837+
case EDEADLK:
2838+
return "EDEADLK";
2839+
case EDOM:
2840+
return "EDOM";
2841+
case EEXIST:
2842+
return "EEXIST";
2843+
case EFAULT:
2844+
return "EFAULT";
2845+
case EFBIG:
2846+
return "EFBIG";
2847+
#ifdef EHOSTUNREACH
2848+
case EHOSTUNREACH:
2849+
return "EHOSTUNREACH";
2850+
#endif
2851+
case EIDRM:
2852+
return "EIDRM";
2853+
case EINPROGRESS:
2854+
return "EINPROGRESS";
2855+
case EINTR:
2856+
return "EINTR";
2857+
case EINVAL:
2858+
return "EINVAL";
2859+
case EIO:
2860+
return "EIO";
2861+
#ifdef EISCONN
2862+
case EISCONN:
2863+
return "EISCONN";
2864+
#endif
2865+
case EISDIR:
2866+
return "EISDIR";
2867+
#ifdef ELOOP
2868+
case ELOOP:
2869+
return "ELOOP";
2870+
#endif
2871+
case EMFILE:
2872+
return "EMFILE";
2873+
case EMLINK:
2874+
return "EMLINK";
2875+
case EMSGSIZE:
2876+
return "EMSGSIZE";
2877+
case ENAMETOOLONG:
2878+
return "ENAMETOOLONG";
2879+
case ENFILE:
2880+
return "ENFILE";
2881+
case ENOBUFS:
2882+
return "ENOBUFS";
2883+
case ENODEV:
2884+
return "ENODEV";
2885+
case ENOENT:
2886+
return "ENOENT";
2887+
case ENOEXEC:
2888+
return "ENOEXEC";
2889+
case ENOMEM:
2890+
return "ENOMEM";
2891+
case ENOSPC:
2892+
return "ENOSPC";
2893+
case ENOSYS:
2894+
return "ENOSYS";
2895+
#ifdef ENOTCONN
2896+
case ENOTCONN:
2897+
return "ENOTCONN";
2898+
#endif
2899+
case ENOTDIR:
2900+
return "ENOTDIR";
2901+
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
2902+
case ENOTEMPTY:
2903+
return "ENOTEMPTY";
2904+
#endif
2905+
#ifdef ENOTSOCK
2906+
case ENOTSOCK:
2907+
return "ENOTSOCK";
2908+
#endif
2909+
#ifdef ENOTSUP
2910+
case ENOTSUP:
2911+
return "ENOTSUP";
2912+
#endif
2913+
case ENOTTY:
2914+
return "ENOTTY";
2915+
case ENXIO:
2916+
return "ENXIO";
2917+
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
2918+
case EOPNOTSUPP:
2919+
return "EOPNOTSUPP";
2920+
#endif
2921+
#ifdef EOVERFLOW
2922+
case EOVERFLOW:
2923+
return "EOVERFLOW";
2924+
#endif
2925+
case EPERM:
2926+
return "EPERM";
2927+
case EPIPE:
2928+
return "EPIPE";
2929+
case EPROTONOSUPPORT:
2930+
return "EPROTONOSUPPORT";
2931+
case ERANGE:
2932+
return "ERANGE";
2933+
#ifdef EROFS
2934+
case EROFS:
2935+
return "EROFS";
2936+
#endif
2937+
case ESRCH:
2938+
return "ESRCH";
2939+
#ifdef ETIMEDOUT
2940+
case ETIMEDOUT:
2941+
return "ETIMEDOUT";
2942+
#endif
2943+
#ifdef ETXTBSY
2944+
case ETXTBSY:
2945+
return "ETXTBSY";
2946+
#endif
2947+
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
2948+
case EWOULDBLOCK:
2949+
return "EWOULDBLOCK";
2950+
#endif
2951+
case EXDEV:
2952+
return "EXDEV";
2953+
}
2954+
2955+
return NULL;
2956+
}
2957+
27792958

27802959
/*
27812960
* error_severity --- get localized string representing elevel

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy