Skip to content

Commit 64f5962

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 8bd5a6a commit 64f5962

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
@@ -170,6 +170,7 @@ static void send_message_to_server_log(ErrorData *edata);
170170
static void send_message_to_frontend(ErrorData *edata);
171171
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
172172
static const char *useful_strerror(int errnum);
173+
static const char *get_errno_symbol(int errnum);
173174
static const char *error_severity(int elevel);
174175
static void append_with_tabs(StringInfo buf, const char *str);
175176
static bool is_log_level_output(int elevel, int log_min_level);
@@ -2784,7 +2785,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
27842785
static const char *
27852786
useful_strerror(int errnum)
27862787
{
2787-
/* this buffer is only used if errno has a bogus value */
2788+
/* this buffer is only used if strerror() and get_errno_symbol() fail */
27882789
static char errorstr_buf[48];
27892790
const char *str;
27902791

@@ -2796,10 +2797,16 @@ useful_strerror(int errnum)
27962797
str = strerror(errnum);
27972798

27982799
/*
2799-
* Some strerror()s return an empty string for out-of-range errno. This is
2800-
* ANSI C spec compliant, but not exactly useful.
2800+
* Some strerror()s return an empty string for out-of-range errno. This
2801+
* is ANSI C spec compliant, but not exactly useful. Also, we may get
2802+
* back strings of question marks if libc cannot transcode the message to
2803+
* the codeset specified by LC_CTYPE. If we get nothing useful, first try
2804+
* get_errno_symbol(), and if that fails, print the numeric errno.
28012805
*/
2802-
if (str == NULL || *str == '\0')
2806+
if (str == NULL || *str == '\0' || *str == '?')
2807+
str = get_errno_symbol(errnum);
2808+
2809+
if (str == NULL)
28032810
{
28042811
snprintf(errorstr_buf, sizeof(errorstr_buf),
28052812
/*------
@@ -2812,6 +2819,178 @@ useful_strerror(int errnum)
28122819
return str;
28132820
}
28142821

2822+
/*
2823+
* Returns a symbol (e.g. "ENOENT") for an errno code.
2824+
* Returns NULL if the code is unrecognized.
2825+
*/
2826+
static const char *
2827+
get_errno_symbol(int errnum)
2828+
{
2829+
switch (errnum)
2830+
{
2831+
case E2BIG:
2832+
return "E2BIG";
2833+
case EACCES:
2834+
return "EACCES";
2835+
#ifdef EADDRINUSE
2836+
case EADDRINUSE:
2837+
return "EADDRINUSE";
2838+
#endif
2839+
#ifdef EADDRNOTAVAIL
2840+
case EADDRNOTAVAIL:
2841+
return "EADDRNOTAVAIL";
2842+
#endif
2843+
case EAFNOSUPPORT:
2844+
return "EAFNOSUPPORT";
2845+
#ifdef EAGAIN
2846+
case EAGAIN:
2847+
return "EAGAIN";
2848+
#endif
2849+
#ifdef EALREADY
2850+
case EALREADY:
2851+
return "EALREADY";
2852+
#endif
2853+
case EBADF:
2854+
return "EBADF";
2855+
#ifdef EBADMSG
2856+
case EBADMSG:
2857+
return "EBADMSG";
2858+
#endif
2859+
case EBUSY:
2860+
return "EBUSY";
2861+
case ECHILD:
2862+
return "ECHILD";
2863+
#ifdef ECONNABORTED
2864+
case ECONNABORTED:
2865+
return "ECONNABORTED";
2866+
#endif
2867+
case ECONNREFUSED:
2868+
return "ECONNREFUSED";
2869+
#ifdef ECONNRESET
2870+
case ECONNRESET:
2871+
return "ECONNRESET";
2872+
#endif
2873+
case EDEADLK:
2874+
return "EDEADLK";
2875+
case EDOM:
2876+
return "EDOM";
2877+
case EEXIST:
2878+
return "EEXIST";
2879+
case EFAULT:
2880+
return "EFAULT";
2881+
case EFBIG:
2882+
return "EFBIG";
2883+
#ifdef EHOSTUNREACH
2884+
case EHOSTUNREACH:
2885+
return "EHOSTUNREACH";
2886+
#endif
2887+
case EIDRM:
2888+
return "EIDRM";
2889+
case EINPROGRESS:
2890+
return "EINPROGRESS";
2891+
case EINTR:
2892+
return "EINTR";
2893+
case EINVAL:
2894+
return "EINVAL";
2895+
case EIO:
2896+
return "EIO";
2897+
#ifdef EISCONN
2898+
case EISCONN:
2899+
return "EISCONN";
2900+
#endif
2901+
case EISDIR:
2902+
return "EISDIR";
2903+
#ifdef ELOOP
2904+
case ELOOP:
2905+
return "ELOOP";
2906+
#endif
2907+
case EMFILE:
2908+
return "EMFILE";
2909+
case EMLINK:
2910+
return "EMLINK";
2911+
case EMSGSIZE:
2912+
return "EMSGSIZE";
2913+
case ENAMETOOLONG:
2914+
return "ENAMETOOLONG";
2915+
case ENFILE:
2916+
return "ENFILE";
2917+
case ENOBUFS:
2918+
return "ENOBUFS";
2919+
case ENODEV:
2920+
return "ENODEV";
2921+
case ENOENT:
2922+
return "ENOENT";
2923+
case ENOEXEC:
2924+
return "ENOEXEC";
2925+
case ENOMEM:
2926+
return "ENOMEM";
2927+
case ENOSPC:
2928+
return "ENOSPC";
2929+
case ENOSYS:
2930+
return "ENOSYS";
2931+
#ifdef ENOTCONN
2932+
case ENOTCONN:
2933+
return "ENOTCONN";
2934+
#endif
2935+
case ENOTDIR:
2936+
return "ENOTDIR";
2937+
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
2938+
case ENOTEMPTY:
2939+
return "ENOTEMPTY";
2940+
#endif
2941+
#ifdef ENOTSOCK
2942+
case ENOTSOCK:
2943+
return "ENOTSOCK";
2944+
#endif
2945+
#ifdef ENOTSUP
2946+
case ENOTSUP:
2947+
return "ENOTSUP";
2948+
#endif
2949+
case ENOTTY:
2950+
return "ENOTTY";
2951+
case ENXIO:
2952+
return "ENXIO";
2953+
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
2954+
case EOPNOTSUPP:
2955+
return "EOPNOTSUPP";
2956+
#endif
2957+
#ifdef EOVERFLOW
2958+
case EOVERFLOW:
2959+
return "EOVERFLOW";
2960+
#endif
2961+
case EPERM:
2962+
return "EPERM";
2963+
case EPIPE:
2964+
return "EPIPE";
2965+
case EPROTONOSUPPORT:
2966+
return "EPROTONOSUPPORT";
2967+
case ERANGE:
2968+
return "ERANGE";
2969+
#ifdef EROFS
2970+
case EROFS:
2971+
return "EROFS";
2972+
#endif
2973+
case ESRCH:
2974+
return "ESRCH";
2975+
#ifdef ETIMEDOUT
2976+
case ETIMEDOUT:
2977+
return "ETIMEDOUT";
2978+
#endif
2979+
#ifdef ETXTBSY
2980+
case ETXTBSY:
2981+
return "ETXTBSY";
2982+
#endif
2983+
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
2984+
case EWOULDBLOCK:
2985+
return "EWOULDBLOCK";
2986+
#endif
2987+
case EXDEV:
2988+
return "EXDEV";
2989+
}
2990+
2991+
return NULL;
2992+
}
2993+
28152994

28162995
/*
28172996
* error_severity --- get localized string representing elevel

0 commit comments

Comments
 (0)