Skip to content

Commit e348043

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 df5d5f1 commit e348043

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
@@ -172,6 +172,7 @@ static void send_message_to_server_log(ErrorData *edata);
172172
static void send_message_to_frontend(ErrorData *edata);
173173
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
174174
static const char *useful_strerror(int errnum);
175+
static const char *get_errno_symbol(int errnum);
175176
static const char *error_severity(int elevel);
176177
static void append_with_tabs(StringInfo buf, const char *str);
177178
static bool is_log_level_output(int elevel, int log_min_level);
@@ -2928,7 +2929,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
29282929
static const char *
29292930
useful_strerror(int errnum)
29302931
{
2931-
/* this buffer is only used if errno has a bogus value */
2932+
/* this buffer is only used if strerror() and get_errno_symbol() fail */
29322933
static char errorstr_buf[48];
29332934
const char *str;
29342935

@@ -2940,10 +2941,16 @@ useful_strerror(int errnum)
29402941
str = strerror(errnum);
29412942

29422943
/*
2943-
* Some strerror()s return an empty string for out-of-range errno. This is
2944-
* ANSI C spec compliant, but not exactly useful.
2944+
* Some strerror()s return an empty string for out-of-range errno. This
2945+
* is ANSI C spec compliant, but not exactly useful. Also, we may get
2946+
* back strings of question marks if libc cannot transcode the message to
2947+
* the codeset specified by LC_CTYPE. If we get nothing useful, first try
2948+
* get_errno_symbol(), and if that fails, print the numeric errno.
29452949
*/
2946-
if (str == NULL || *str == '\0')
2950+
if (str == NULL || *str == '\0' || *str == '?')
2951+
str = get_errno_symbol(errnum);
2952+
2953+
if (str == NULL)
29472954
{
29482955
snprintf(errorstr_buf, sizeof(errorstr_buf),
29492956
/*------
@@ -2956,6 +2963,178 @@ useful_strerror(int errnum)
29562963
return str;
29572964
}
29582965

2966+
/*
2967+
* Returns a symbol (e.g. "ENOENT") for an errno code.
2968+
* Returns NULL if the code is unrecognized.
2969+
*/
2970+
static const char *
2971+
get_errno_symbol(int errnum)
2972+
{
2973+
switch (errnum)
2974+
{
2975+
case E2BIG:
2976+
return "E2BIG";
2977+
case EACCES:
2978+
return "EACCES";
2979+
#ifdef EADDRINUSE
2980+
case EADDRINUSE:
2981+
return "EADDRINUSE";
2982+
#endif
2983+
#ifdef EADDRNOTAVAIL
2984+
case EADDRNOTAVAIL:
2985+
return "EADDRNOTAVAIL";
2986+
#endif
2987+
case EAFNOSUPPORT:
2988+
return "EAFNOSUPPORT";
2989+
#ifdef EAGAIN
2990+
case EAGAIN:
2991+
return "EAGAIN";
2992+
#endif
2993+
#ifdef EALREADY
2994+
case EALREADY:
2995+
return "EALREADY";
2996+
#endif
2997+
case EBADF:
2998+
return "EBADF";
2999+
#ifdef EBADMSG
3000+
case EBADMSG:
3001+
return "EBADMSG";
3002+
#endif
3003+
case EBUSY:
3004+
return "EBUSY";
3005+
case ECHILD:
3006+
return "ECHILD";
3007+
#ifdef ECONNABORTED
3008+
case ECONNABORTED:
3009+
return "ECONNABORTED";
3010+
#endif
3011+
case ECONNREFUSED:
3012+
return "ECONNREFUSED";
3013+
#ifdef ECONNRESET
3014+
case ECONNRESET:
3015+
return "ECONNRESET";
3016+
#endif
3017+
case EDEADLK:
3018+
return "EDEADLK";
3019+
case EDOM:
3020+
return "EDOM";
3021+
case EEXIST:
3022+
return "EEXIST";
3023+
case EFAULT:
3024+
return "EFAULT";
3025+
case EFBIG:
3026+
return "EFBIG";
3027+
#ifdef EHOSTUNREACH
3028+
case EHOSTUNREACH:
3029+
return "EHOSTUNREACH";
3030+
#endif
3031+
case EIDRM:
3032+
return "EIDRM";
3033+
case EINPROGRESS:
3034+
return "EINPROGRESS";
3035+
case EINTR:
3036+
return "EINTR";
3037+
case EINVAL:
3038+
return "EINVAL";
3039+
case EIO:
3040+
return "EIO";
3041+
#ifdef EISCONN
3042+
case EISCONN:
3043+
return "EISCONN";
3044+
#endif
3045+
case EISDIR:
3046+
return "EISDIR";
3047+
#ifdef ELOOP
3048+
case ELOOP:
3049+
return "ELOOP";
3050+
#endif
3051+
case EMFILE:
3052+
return "EMFILE";
3053+
case EMLINK:
3054+
return "EMLINK";
3055+
case EMSGSIZE:
3056+
return "EMSGSIZE";
3057+
case ENAMETOOLONG:
3058+
return "ENAMETOOLONG";
3059+
case ENFILE:
3060+
return "ENFILE";
3061+
case ENOBUFS:
3062+
return "ENOBUFS";
3063+
case ENODEV:
3064+
return "ENODEV";
3065+
case ENOENT:
3066+
return "ENOENT";
3067+
case ENOEXEC:
3068+
return "ENOEXEC";
3069+
case ENOMEM:
3070+
return "ENOMEM";
3071+
case ENOSPC:
3072+
return "ENOSPC";
3073+
case ENOSYS:
3074+
return "ENOSYS";
3075+
#ifdef ENOTCONN
3076+
case ENOTCONN:
3077+
return "ENOTCONN";
3078+
#endif
3079+
case ENOTDIR:
3080+
return "ENOTDIR";
3081+
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
3082+
case ENOTEMPTY:
3083+
return "ENOTEMPTY";
3084+
#endif
3085+
#ifdef ENOTSOCK
3086+
case ENOTSOCK:
3087+
return "ENOTSOCK";
3088+
#endif
3089+
#ifdef ENOTSUP
3090+
case ENOTSUP:
3091+
return "ENOTSUP";
3092+
#endif
3093+
case ENOTTY:
3094+
return "ENOTTY";
3095+
case ENXIO:
3096+
return "ENXIO";
3097+
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
3098+
case EOPNOTSUPP:
3099+
return "EOPNOTSUPP";
3100+
#endif
3101+
#ifdef EOVERFLOW
3102+
case EOVERFLOW:
3103+
return "EOVERFLOW";
3104+
#endif
3105+
case EPERM:
3106+
return "EPERM";
3107+
case EPIPE:
3108+
return "EPIPE";
3109+
case EPROTONOSUPPORT:
3110+
return "EPROTONOSUPPORT";
3111+
case ERANGE:
3112+
return "ERANGE";
3113+
#ifdef EROFS
3114+
case EROFS:
3115+
return "EROFS";
3116+
#endif
3117+
case ESRCH:
3118+
return "ESRCH";
3119+
#ifdef ETIMEDOUT
3120+
case ETIMEDOUT:
3121+
return "ETIMEDOUT";
3122+
#endif
3123+
#ifdef ETXTBSY
3124+
case ETXTBSY:
3125+
return "ETXTBSY";
3126+
#endif
3127+
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
3128+
case EWOULDBLOCK:
3129+
return "EWOULDBLOCK";
3130+
#endif
3131+
case EXDEV:
3132+
return "EXDEV";
3133+
}
3134+
3135+
return NULL;
3136+
}
3137+
29593138

29603139
/*
29613140
* error_severity --- get localized string representing elevel

0 commit comments

Comments
 (0)