mirror of
https://github.com/postgres/postgres.git
synced 2025-11-15 03:41:20 +03:00
Be more robust when strerror() doesn't give a useful result.
Back-patch commits8e68816cc2and8dace66e07into the stable branches. Buildfarm testing revealed no great portability surprises, and it seems useful to have this robustness improvement in all branches.
This commit is contained in:
@@ -170,6 +170,7 @@ static void send_message_to_server_log(ErrorData *edata);
|
|||||||
static void send_message_to_frontend(ErrorData *edata);
|
static void send_message_to_frontend(ErrorData *edata);
|
||||||
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
|
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
|
||||||
static const char *useful_strerror(int errnum);
|
static const char *useful_strerror(int errnum);
|
||||||
|
static const char *get_errno_symbol(int errnum);
|
||||||
static const char *error_severity(int elevel);
|
static const char *error_severity(int elevel);
|
||||||
static void append_with_tabs(StringInfo buf, const char *str);
|
static void append_with_tabs(StringInfo buf, const char *str);
|
||||||
static bool is_log_level_output(int elevel, int log_min_level);
|
static bool is_log_level_output(int elevel, int log_min_level);
|
||||||
@@ -2784,7 +2785,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
|
|||||||
static const char *
|
static const char *
|
||||||
useful_strerror(int errnum)
|
useful_strerror(int errnum)
|
||||||
{
|
{
|
||||||
/* this buffer is only used if errno has a bogus value */
|
/* this buffer is only used if strerror() and get_errno_symbol() fail */
|
||||||
static char errorstr_buf[48];
|
static char errorstr_buf[48];
|
||||||
const char *str;
|
const char *str;
|
||||||
|
|
||||||
@@ -2796,10 +2797,16 @@ useful_strerror(int errnum)
|
|||||||
str = strerror(errnum);
|
str = strerror(errnum);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Some strerror()s return an empty string for out-of-range errno. This is
|
* Some strerror()s return an empty string for out-of-range errno. This
|
||||||
* ANSI C spec compliant, but not exactly useful.
|
* is ANSI C spec compliant, but not exactly useful. Also, we may get
|
||||||
|
* back strings of question marks if libc cannot transcode the message to
|
||||||
|
* the codeset specified by LC_CTYPE. If we get nothing useful, first try
|
||||||
|
* get_errno_symbol(), and if that fails, print the numeric errno.
|
||||||
*/
|
*/
|
||||||
if (str == NULL || *str == '\0')
|
if (str == NULL || *str == '\0' || *str == '?')
|
||||||
|
str = get_errno_symbol(errnum);
|
||||||
|
|
||||||
|
if (str == NULL)
|
||||||
{
|
{
|
||||||
snprintf(errorstr_buf, sizeof(errorstr_buf),
|
snprintf(errorstr_buf, sizeof(errorstr_buf),
|
||||||
/*------
|
/*------
|
||||||
@@ -2812,6 +2819,178 @@ useful_strerror(int errnum)
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns a symbol (e.g. "ENOENT") for an errno code.
|
||||||
|
* Returns NULL if the code is unrecognized.
|
||||||
|
*/
|
||||||
|
static const char *
|
||||||
|
get_errno_symbol(int errnum)
|
||||||
|
{
|
||||||
|
switch (errnum)
|
||||||
|
{
|
||||||
|
case E2BIG:
|
||||||
|
return "E2BIG";
|
||||||
|
case EACCES:
|
||||||
|
return "EACCES";
|
||||||
|
#ifdef EADDRINUSE
|
||||||
|
case EADDRINUSE:
|
||||||
|
return "EADDRINUSE";
|
||||||
|
#endif
|
||||||
|
#ifdef EADDRNOTAVAIL
|
||||||
|
case EADDRNOTAVAIL:
|
||||||
|
return "EADDRNOTAVAIL";
|
||||||
|
#endif
|
||||||
|
case EAFNOSUPPORT:
|
||||||
|
return "EAFNOSUPPORT";
|
||||||
|
#ifdef EAGAIN
|
||||||
|
case EAGAIN:
|
||||||
|
return "EAGAIN";
|
||||||
|
#endif
|
||||||
|
#ifdef EALREADY
|
||||||
|
case EALREADY:
|
||||||
|
return "EALREADY";
|
||||||
|
#endif
|
||||||
|
case EBADF:
|
||||||
|
return "EBADF";
|
||||||
|
#ifdef EBADMSG
|
||||||
|
case EBADMSG:
|
||||||
|
return "EBADMSG";
|
||||||
|
#endif
|
||||||
|
case EBUSY:
|
||||||
|
return "EBUSY";
|
||||||
|
case ECHILD:
|
||||||
|
return "ECHILD";
|
||||||
|
#ifdef ECONNABORTED
|
||||||
|
case ECONNABORTED:
|
||||||
|
return "ECONNABORTED";
|
||||||
|
#endif
|
||||||
|
case ECONNREFUSED:
|
||||||
|
return "ECONNREFUSED";
|
||||||
|
#ifdef ECONNRESET
|
||||||
|
case ECONNRESET:
|
||||||
|
return "ECONNRESET";
|
||||||
|
#endif
|
||||||
|
case EDEADLK:
|
||||||
|
return "EDEADLK";
|
||||||
|
case EDOM:
|
||||||
|
return "EDOM";
|
||||||
|
case EEXIST:
|
||||||
|
return "EEXIST";
|
||||||
|
case EFAULT:
|
||||||
|
return "EFAULT";
|
||||||
|
case EFBIG:
|
||||||
|
return "EFBIG";
|
||||||
|
#ifdef EHOSTUNREACH
|
||||||
|
case EHOSTUNREACH:
|
||||||
|
return "EHOSTUNREACH";
|
||||||
|
#endif
|
||||||
|
case EIDRM:
|
||||||
|
return "EIDRM";
|
||||||
|
case EINPROGRESS:
|
||||||
|
return "EINPROGRESS";
|
||||||
|
case EINTR:
|
||||||
|
return "EINTR";
|
||||||
|
case EINVAL:
|
||||||
|
return "EINVAL";
|
||||||
|
case EIO:
|
||||||
|
return "EIO";
|
||||||
|
#ifdef EISCONN
|
||||||
|
case EISCONN:
|
||||||
|
return "EISCONN";
|
||||||
|
#endif
|
||||||
|
case EISDIR:
|
||||||
|
return "EISDIR";
|
||||||
|
#ifdef ELOOP
|
||||||
|
case ELOOP:
|
||||||
|
return "ELOOP";
|
||||||
|
#endif
|
||||||
|
case EMFILE:
|
||||||
|
return "EMFILE";
|
||||||
|
case EMLINK:
|
||||||
|
return "EMLINK";
|
||||||
|
case EMSGSIZE:
|
||||||
|
return "EMSGSIZE";
|
||||||
|
case ENAMETOOLONG:
|
||||||
|
return "ENAMETOOLONG";
|
||||||
|
case ENFILE:
|
||||||
|
return "ENFILE";
|
||||||
|
case ENOBUFS:
|
||||||
|
return "ENOBUFS";
|
||||||
|
case ENODEV:
|
||||||
|
return "ENODEV";
|
||||||
|
case ENOENT:
|
||||||
|
return "ENOENT";
|
||||||
|
case ENOEXEC:
|
||||||
|
return "ENOEXEC";
|
||||||
|
case ENOMEM:
|
||||||
|
return "ENOMEM";
|
||||||
|
case ENOSPC:
|
||||||
|
return "ENOSPC";
|
||||||
|
case ENOSYS:
|
||||||
|
return "ENOSYS";
|
||||||
|
#ifdef ENOTCONN
|
||||||
|
case ENOTCONN:
|
||||||
|
return "ENOTCONN";
|
||||||
|
#endif
|
||||||
|
case ENOTDIR:
|
||||||
|
return "ENOTDIR";
|
||||||
|
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
|
||||||
|
case ENOTEMPTY:
|
||||||
|
return "ENOTEMPTY";
|
||||||
|
#endif
|
||||||
|
#ifdef ENOTSOCK
|
||||||
|
case ENOTSOCK:
|
||||||
|
return "ENOTSOCK";
|
||||||
|
#endif
|
||||||
|
#ifdef ENOTSUP
|
||||||
|
case ENOTSUP:
|
||||||
|
return "ENOTSUP";
|
||||||
|
#endif
|
||||||
|
case ENOTTY:
|
||||||
|
return "ENOTTY";
|
||||||
|
case ENXIO:
|
||||||
|
return "ENXIO";
|
||||||
|
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
|
||||||
|
case EOPNOTSUPP:
|
||||||
|
return "EOPNOTSUPP";
|
||||||
|
#endif
|
||||||
|
#ifdef EOVERFLOW
|
||||||
|
case EOVERFLOW:
|
||||||
|
return "EOVERFLOW";
|
||||||
|
#endif
|
||||||
|
case EPERM:
|
||||||
|
return "EPERM";
|
||||||
|
case EPIPE:
|
||||||
|
return "EPIPE";
|
||||||
|
case EPROTONOSUPPORT:
|
||||||
|
return "EPROTONOSUPPORT";
|
||||||
|
case ERANGE:
|
||||||
|
return "ERANGE";
|
||||||
|
#ifdef EROFS
|
||||||
|
case EROFS:
|
||||||
|
return "EROFS";
|
||||||
|
#endif
|
||||||
|
case ESRCH:
|
||||||
|
return "ESRCH";
|
||||||
|
#ifdef ETIMEDOUT
|
||||||
|
case ETIMEDOUT:
|
||||||
|
return "ETIMEDOUT";
|
||||||
|
#endif
|
||||||
|
#ifdef ETXTBSY
|
||||||
|
case ETXTBSY:
|
||||||
|
return "ETXTBSY";
|
||||||
|
#endif
|
||||||
|
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
|
||||||
|
case EWOULDBLOCK:
|
||||||
|
return "EWOULDBLOCK";
|
||||||
|
#endif
|
||||||
|
case EXDEV:
|
||||||
|
return "EXDEV";
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* error_severity --- get localized string representing elevel
|
* error_severity --- get localized string representing elevel
|
||||||
|
|||||||
Reference in New Issue
Block a user