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)