Skip to content

Commit 8103f49

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 352ab59 commit 8103f49

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
@@ -153,6 +153,7 @@ static void send_message_to_server_log(ErrorData *edata);
153153
static void send_message_to_frontend(ErrorData *edata);
154154
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
155155
static const char *useful_strerror(int errnum);
156+
static const char *get_errno_symbol(int errnum);
156157
static const char *error_severity(int elevel);
157158
static void append_with_tabs(StringInfo buf, const char *str);
158159
static bool is_log_level_output(int elevel, int log_min_level);
@@ -2650,7 +2651,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
26502651
static const char *
26512652
useful_strerror(int errnum)
26522653
{
2653-
/* this buffer is only used if errno has a bogus value */
2654+
/* this buffer is only used if strerror() and get_errno_symbol() fail */
26542655
static char errorstr_buf[48];
26552656
const char *str;
26562657

@@ -2662,10 +2663,16 @@ useful_strerror(int errnum)
26622663
str = strerror(errnum);
26632664

26642665
/*
2665-
* Some strerror()s return an empty string for out-of-range errno. This is
2666-
* ANSI C spec compliant, but not exactly useful.
2666+
* Some strerror()s return an empty string for out-of-range errno. This
2667+
* is ANSI C spec compliant, but not exactly useful. Also, we may get
2668+
* back strings of question marks if libc cannot transcode the message to
2669+
* the codeset specified by LC_CTYPE. If we get nothing useful, first try
2670+
* get_errno_symbol(), and if that fails, print the numeric errno.
26672671
*/
2668-
if (str == NULL || *str == '\0')
2672+
if (str == NULL || *str == '\0' || *str == '?')
2673+
str = get_errno_symbol(errnum);
2674+
2675+
if (str == NULL)
26692676
{
26702677
snprintf(errorstr_buf, sizeof(errorstr_buf),
26712678
/*------
@@ -2678,6 +2685,178 @@ useful_strerror(int errnum)
26782685
return str;
26792686
}
26802687

2688+
/*
2689+
* Returns a symbol (e.g. "ENOENT") for an errno code.
2690+
* Returns NULL if the code is unrecognized.
2691+
*/
2692+
static const char *
2693+
get_errno_symbol(int errnum)
2694+
{
2695+
switch (errnum)
2696+
{
2697+
case E2BIG:
2698+
return "E2BIG";
2699+
case EACCES:
2700+
return "EACCES";
2701+
#ifdef EADDRINUSE
2702+
case EADDRINUSE:
2703+
return "EADDRINUSE";
2704+
#endif
2705+
#ifdef EADDRNOTAVAIL
2706+
case EADDRNOTAVAIL:
2707+
return "EADDRNOTAVAIL";
2708+
#endif
2709+
case EAFNOSUPPORT:
2710+
return "EAFNOSUPPORT";
2711+
#ifdef EAGAIN
2712+
case EAGAIN:
2713+
return "EAGAIN";
2714+
#endif
2715+
#ifdef EALREADY
2716+
case EALREADY:
2717+
return "EALREADY";
2718+
#endif
2719+
case EBADF:
2720+
return "EBADF";
2721+
#ifdef EBADMSG
2722+
case EBADMSG:
2723+
return "EBADMSG";
2724+
#endif
2725+
case EBUSY:
2726+
return "EBUSY";
2727+
case ECHILD:
2728+
return "ECHILD";
2729+
#ifdef ECONNABORTED
2730+
case ECONNABORTED:
2731+
return "ECONNABORTED";
2732+
#endif
2733+
case ECONNREFUSED:
2734+
return "ECONNREFUSED";
2735+
#ifdef ECONNRESET
2736+
case ECONNRESET:
2737+
return "ECONNRESET";
2738+
#endif
2739+
case EDEADLK:
2740+
return "EDEADLK";
2741+
case EDOM:
2742+
return "EDOM";
2743+
case EEXIST:
2744+
return "EEXIST";
2745+
case EFAULT:
2746+
return "EFAULT";
2747+
case EFBIG:
2748+
return "EFBIG";
2749+
#ifdef EHOSTUNREACH
2750+
case EHOSTUNREACH:
2751+
return "EHOSTUNREACH";
2752+
#endif
2753+
case EIDRM:
2754+
return "EIDRM";
2755+
case EINPROGRESS:
2756+
return "EINPROGRESS";
2757+
case EINTR:
2758+
return "EINTR";
2759+
case EINVAL:
2760+
return "EINVAL";
2761+
case EIO:
2762+
return "EIO";
2763+
#ifdef EISCONN
2764+
case EISCONN:
2765+
return "EISCONN";
2766+
#endif
2767+
case EISDIR:
2768+
return "EISDIR";
2769+
#ifdef ELOOP
2770+
case ELOOP:
2771+
return "ELOOP";
2772+
#endif
2773+
case EMFILE:
2774+
return "EMFILE";
2775+
case EMLINK:
2776+
return "EMLINK";
2777+
case EMSGSIZE:
2778+
return "EMSGSIZE";
2779+
case ENAMETOOLONG:
2780+
return "ENAMETOOLONG";
2781+
case ENFILE:
2782+
return "ENFILE";
2783+
case ENOBUFS:
2784+
return "ENOBUFS";
2785+
case ENODEV:
2786+
return "ENODEV";
2787+
case ENOENT:
2788+
return "ENOENT";
2789+
case ENOEXEC:
2790+
return "ENOEXEC";
2791+
case ENOMEM:
2792+
return "ENOMEM";
2793+
case ENOSPC:
2794+
return "ENOSPC";
2795+
case ENOSYS:
2796+
return "ENOSYS";
2797+
#ifdef ENOTCONN
2798+
case ENOTCONN:
2799+
return "ENOTCONN";
2800+
#endif
2801+
case ENOTDIR:
2802+
return "ENOTDIR";
2803+
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
2804+
case ENOTEMPTY:
2805+
return "ENOTEMPTY";
2806+
#endif
2807+
#ifdef ENOTSOCK
2808+
case ENOTSOCK:
2809+
return "ENOTSOCK";
2810+
#endif
2811+
#ifdef ENOTSUP
2812+
case ENOTSUP:
2813+
return "ENOTSUP";
2814+
#endif
2815+
case ENOTTY:
2816+
return "ENOTTY";
2817+
case ENXIO:
2818+
return "ENXIO";
2819+
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
2820+
case EOPNOTSUPP:
2821+
return "EOPNOTSUPP";
2822+
#endif
2823+
#ifdef EOVERFLOW
2824+
case EOVERFLOW:
2825+
return "EOVERFLOW";
2826+
#endif
2827+
case EPERM:
2828+
return "EPERM";
2829+
case EPIPE:
2830+
return "EPIPE";
2831+
case EPROTONOSUPPORT:
2832+
return "EPROTONOSUPPORT";
2833+
case ERANGE:
2834+
return "ERANGE";
2835+
#ifdef EROFS
2836+
case EROFS:
2837+
return "EROFS";
2838+
#endif
2839+
case ESRCH:
2840+
return "ESRCH";
2841+
#ifdef ETIMEDOUT
2842+
case ETIMEDOUT:
2843+
return "ETIMEDOUT";
2844+
#endif
2845+
#ifdef ETXTBSY
2846+
case ETXTBSY:
2847+
return "ETXTBSY";
2848+
#endif
2849+
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
2850+
case EWOULDBLOCK:
2851+
return "EWOULDBLOCK";
2852+
#endif
2853+
case EXDEV:
2854+
return "EXDEV";
2855+
}
2856+
2857+
return NULL;
2858+
}
2859+
26812860

26822861
/*
26832862
* error_severity --- get localized string representing elevel

0 commit comments

Comments
 (0)