Skip to content

Commit 26e9d4d

Browse files
committed
Convert elog.c's useful_strerror() into a globally-used strerror wrapper.
elog.c has long had a private strerror wrapper that handles assorted possible failures or deficiencies of the platform's strerror. On Windows, it also knows how to translate Winsock error codes, which the native strerror does not. Move all this code into src/port/strerror.c and define strerror() as a macro that invokes it, so that both our frontend and backend code will have all of this behavior. I believe this constitutes an actual bug fix on Windows, since AFAICS our frontend code did not report Winsock error codes properly before this. However, the main point is to lay the groundwork for implementing %m in src/port/snprintf.c: the behavior we want %m to have is this one, not the native strerror's. Note that this throws away the prior use of src/port/strerror.c, which was to implement strerror() on platforms lacking it. That's been dead code for nigh twenty years now, since strerror() was already required by C89. We should likewise cause strerror_r to use this behavior, but I'll tackle that separately. Patch by me, reviewed by Michael Paquier Discussion: https://postgr.es/m/2975.1526862605@sss.pgh.pa.us
1 parent a49ceda commit 26e9d4d

File tree

19 files changed

+299
-311
lines changed

19 files changed

+299
-311
lines changed

configure

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15644,19 +15644,6 @@ esac
1564415644

1564515645
fi
1564615646

15647-
ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror"
15648-
if test "x$ac_cv_func_strerror" = xyes; then :
15649-
$as_echo "#define HAVE_STRERROR 1" >>confdefs.h
15650-
15651-
else
15652-
case " $LIBOBJS " in
15653-
*" strerror.$ac_objext "* ) ;;
15654-
*) LIBOBJS="$LIBOBJS strerror.$ac_objext"
15655-
;;
15656-
esac
15657-
15658-
fi
15659-
1566015647
ac_fn_c_check_func "$LINENO" "strlcat" "ac_cv_func_strlcat"
1566115648
if test "x$ac_cv_func_strlcat" = xyes; then :
1566215649
$as_echo "#define HAVE_STRLCAT 1" >>confdefs.h

configure.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,7 @@ else
16871687
AC_CHECK_FUNCS([fpclass fp_class fp_class_d class], [break])
16881688
fi
16891689

1690-
AC_REPLACE_FUNCS([crypt dlopen fls getopt getrusage inet_aton mkdtemp random rint srandom strerror strlcat strlcpy strnlen])
1690+
AC_REPLACE_FUNCS([crypt dlopen fls getopt getrusage inet_aton mkdtemp random rint srandom strlcat strlcpy strnlen])
16911691

16921692
case $host_os in
16931693

src/backend/port/win32/socket.c

Lines changed: 0 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -690,39 +690,3 @@ pgwin32_select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, c
690690
memcpy(writefds, &outwritefds, sizeof(fd_set));
691691
return nummatches;
692692
}
693-
694-
695-
/*
696-
* Return win32 error string, since strerror can't
697-
* handle winsock codes
698-
*/
699-
static char wserrbuf[256];
700-
const char *
701-
pgwin32_socket_strerror(int err)
702-
{
703-
static HANDLE handleDLL = INVALID_HANDLE_VALUE;
704-
705-
if (handleDLL == INVALID_HANDLE_VALUE)
706-
{
707-
handleDLL = LoadLibraryEx("netmsg.dll", NULL, DONT_RESOLVE_DLL_REFERENCES | LOAD_LIBRARY_AS_DATAFILE);
708-
if (handleDLL == NULL)
709-
ereport(FATAL,
710-
(errmsg_internal("could not load netmsg.dll: error code %lu", GetLastError())));
711-
}
712-
713-
ZeroMemory(&wserrbuf, sizeof(wserrbuf));
714-
if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS |
715-
FORMAT_MESSAGE_FROM_SYSTEM |
716-
FORMAT_MESSAGE_FROM_HMODULE,
717-
handleDLL,
718-
err,
719-
MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
720-
wserrbuf,
721-
sizeof(wserrbuf) - 1,
722-
NULL) == 0)
723-
{
724-
/* Failed to get id */
725-
sprintf(wserrbuf, "unrecognized winsock error %d", err);
726-
}
727-
return wserrbuf;
728-
}

src/backend/utils/error/elog.c

Lines changed: 1 addition & 216 deletions
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,6 @@ static void send_message_to_server_log(ErrorData *edata);
178178
static void write_pipe_chunks(char *data, int len, int dest);
179179
static void send_message_to_frontend(ErrorData *edata);
180180
static char *expand_fmt_string(const char *fmt, ErrorData *edata);
181-
static const char *useful_strerror(int errnum);
182-
static const char *get_errno_symbol(int errnum);
183181
static const char *error_severity(int elevel);
184182
static void append_with_tabs(StringInfo buf, const char *str);
185183
static bool is_log_level_output(int elevel, int log_min_level);
@@ -3360,7 +3358,7 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
33603358
*/
33613359
const char *cp2;
33623360

3363-
cp2 = useful_strerror(edata->saved_errno);
3361+
cp2 = strerror(edata->saved_errno);
33643362
for (; *cp2; cp2++)
33653363
{
33663364
if (*cp2 == '%')
@@ -3383,219 +3381,6 @@ expand_fmt_string(const char *fmt, ErrorData *edata)
33833381
}
33843382

33853383

3386-
/*
3387-
* A slightly cleaned-up version of strerror()
3388-
*/
3389-
static const char *
3390-
useful_strerror(int errnum)
3391-
{
3392-
/* this buffer is only used if strerror() and get_errno_symbol() fail */
3393-
static char errorstr_buf[48];
3394-
const char *str;
3395-
3396-
#ifdef WIN32
3397-
/* Winsock error code range, per WinError.h */
3398-
if (errnum >= 10000 && errnum <= 11999)
3399-
return pgwin32_socket_strerror(errnum);
3400-
#endif
3401-
str = strerror(errnum);
3402-
3403-
/*
3404-
* Some strerror()s return an empty string for out-of-range errno. This
3405-
* is ANSI C spec compliant, but not exactly useful. Also, we may get
3406-
* back strings of question marks if libc cannot transcode the message to
3407-
* the codeset specified by LC_CTYPE. If we get nothing useful, first try
3408-
* get_errno_symbol(), and if that fails, print the numeric errno.
3409-
*/
3410-
if (str == NULL || *str == '\0' || *str == '?')
3411-
str = get_errno_symbol(errnum);
3412-
3413-
if (str == NULL)
3414-
{
3415-
snprintf(errorstr_buf, sizeof(errorstr_buf),
3416-
/*------
3417-
translator: This string will be truncated at 47
3418-
characters expanded. */
3419-
_("operating system error %d"), errnum);
3420-
str = errorstr_buf;
3421-
}
3422-
3423-
return str;
3424-
}
3425-
3426-
/*
3427-
* Returns a symbol (e.g. "ENOENT") for an errno code.
3428-
* Returns NULL if the code is unrecognized.
3429-
*/
3430-
static const char *
3431-
get_errno_symbol(int errnum)
3432-
{
3433-
switch (errnum)
3434-
{
3435-
case E2BIG:
3436-
return "E2BIG";
3437-
case EACCES:
3438-
return "EACCES";
3439-
#ifdef EADDRINUSE
3440-
case EADDRINUSE:
3441-
return "EADDRINUSE";
3442-
#endif
3443-
#ifdef EADDRNOTAVAIL
3444-
case EADDRNOTAVAIL:
3445-
return "EADDRNOTAVAIL";
3446-
#endif
3447-
case EAFNOSUPPORT:
3448-
return "EAFNOSUPPORT";
3449-
#ifdef EAGAIN
3450-
case EAGAIN:
3451-
return "EAGAIN";
3452-
#endif
3453-
#ifdef EALREADY
3454-
case EALREADY:
3455-
return "EALREADY";
3456-
#endif
3457-
case EBADF:
3458-
return "EBADF";
3459-
#ifdef EBADMSG
3460-
case EBADMSG:
3461-
return "EBADMSG";
3462-
#endif
3463-
case EBUSY:
3464-
return "EBUSY";
3465-
case ECHILD:
3466-
return "ECHILD";
3467-
#ifdef ECONNABORTED
3468-
case ECONNABORTED:
3469-
return "ECONNABORTED";
3470-
#endif
3471-
case ECONNREFUSED:
3472-
return "ECONNREFUSED";
3473-
#ifdef ECONNRESET
3474-
case ECONNRESET:
3475-
return "ECONNRESET";
3476-
#endif
3477-
case EDEADLK:
3478-
return "EDEADLK";
3479-
case EDOM:
3480-
return "EDOM";
3481-
case EEXIST:
3482-
return "EEXIST";
3483-
case EFAULT:
3484-
return "EFAULT";
3485-
case EFBIG:
3486-
return "EFBIG";
3487-
#ifdef EHOSTUNREACH
3488-
case EHOSTUNREACH:
3489-
return "EHOSTUNREACH";
3490-
#endif
3491-
case EIDRM:
3492-
return "EIDRM";
3493-
case EINPROGRESS:
3494-
return "EINPROGRESS";
3495-
case EINTR:
3496-
return "EINTR";
3497-
case EINVAL:
3498-
return "EINVAL";
3499-
case EIO:
3500-
return "EIO";
3501-
#ifdef EISCONN
3502-
case EISCONN:
3503-
return "EISCONN";
3504-
#endif
3505-
case EISDIR:
3506-
return "EISDIR";
3507-
#ifdef ELOOP
3508-
case ELOOP:
3509-
return "ELOOP";
3510-
#endif
3511-
case EMFILE:
3512-
return "EMFILE";
3513-
case EMLINK:
3514-
return "EMLINK";
3515-
case EMSGSIZE:
3516-
return "EMSGSIZE";
3517-
case ENAMETOOLONG:
3518-
return "ENAMETOOLONG";
3519-
case ENFILE:
3520-
return "ENFILE";
3521-
case ENOBUFS:
3522-
return "ENOBUFS";
3523-
case ENODEV:
3524-
return "ENODEV";
3525-
case ENOENT:
3526-
return "ENOENT";
3527-
case ENOEXEC:
3528-
return "ENOEXEC";
3529-
case ENOMEM:
3530-
return "ENOMEM";
3531-
case ENOSPC:
3532-
return "ENOSPC";
3533-
case ENOSYS:
3534-
return "ENOSYS";
3535-
#ifdef ENOTCONN
3536-
case ENOTCONN:
3537-
return "ENOTCONN";
3538-
#endif
3539-
case ENOTDIR:
3540-
return "ENOTDIR";
3541-
#if defined(ENOTEMPTY) && (ENOTEMPTY != EEXIST) /* same code on AIX */
3542-
case ENOTEMPTY:
3543-
return "ENOTEMPTY";
3544-
#endif
3545-
#ifdef ENOTSOCK
3546-
case ENOTSOCK:
3547-
return "ENOTSOCK";
3548-
#endif
3549-
#ifdef ENOTSUP
3550-
case ENOTSUP:
3551-
return "ENOTSUP";
3552-
#endif
3553-
case ENOTTY:
3554-
return "ENOTTY";
3555-
case ENXIO:
3556-
return "ENXIO";
3557-
#if defined(EOPNOTSUPP) && (!defined(ENOTSUP) || (EOPNOTSUPP != ENOTSUP))
3558-
case EOPNOTSUPP:
3559-
return "EOPNOTSUPP";
3560-
#endif
3561-
#ifdef EOVERFLOW
3562-
case EOVERFLOW:
3563-
return "EOVERFLOW";
3564-
#endif
3565-
case EPERM:
3566-
return "EPERM";
3567-
case EPIPE:
3568-
return "EPIPE";
3569-
case EPROTONOSUPPORT:
3570-
return "EPROTONOSUPPORT";
3571-
case ERANGE:
3572-
return "ERANGE";
3573-
#ifdef EROFS
3574-
case EROFS:
3575-
return "EROFS";
3576-
#endif
3577-
case ESRCH:
3578-
return "ESRCH";
3579-
#ifdef ETIMEDOUT
3580-
case ETIMEDOUT:
3581-
return "ETIMEDOUT";
3582-
#endif
3583-
#ifdef ETXTBSY
3584-
case ETXTBSY:
3585-
return "ETXTBSY";
3586-
#endif
3587-
#if defined(EWOULDBLOCK) && (!defined(EAGAIN) || (EWOULDBLOCK != EAGAIN))
3588-
case EWOULDBLOCK:
3589-
return "EWOULDBLOCK";
3590-
#endif
3591-
case EXDEV:
3592-
return "EXDEV";
3593-
}
3594-
3595-
return NULL;
3596-
}
3597-
3598-
35993384
/*
36003385
* error_severity --- get string representing elevel
36013386
*

src/include/pg_config.h.in

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -534,9 +534,6 @@
534534
/* Define to 1 if you have the <stdlib.h> header file. */
535535
#undef HAVE_STDLIB_H
536536

537-
/* Define to 1 if you have the `strerror' function. */
538-
#undef HAVE_STRERROR
539-
540537
/* Define to 1 if you have the `strerror_r' function. */
541538
#undef HAVE_STRERROR_R
542539

src/include/pg_config.h.win32

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -405,11 +405,6 @@
405405
/* Define to 1 if you have the <stdlib.h> header file. */
406406
#define HAVE_STDLIB_H 1
407407

408-
/* Define to 1 if you have the `strerror' function. */
409-
#ifndef HAVE_STRERROR
410-
#define HAVE_STRERROR 1
411-
#endif
412-
413408
/* Define to 1 if you have the `strerror_r' function. */
414409
/* #undef HAVE_STRERROR_R */
415410

src/include/port.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ extern int pg_printf(const char *fmt,...) pg_attribute_printf(1, 2);
189189
#endif
190190
#endif /* USE_REPL_SNPRINTF */
191191

192+
/* Replace strerror() with our own, somewhat more robust wrapper */
193+
extern char *pg_strerror(int errnum);
194+
#define strerror pg_strerror
195+
192196
/* Portable prompt handling */
193197
extern void simple_prompt(const char *prompt, char *destination, size_t destlen,
194198
bool echo);
@@ -355,7 +359,7 @@ extern int isinf(double x);
355359
#undef isinf
356360
#define isinf __builtin_isinf
357361
#endif /* __has_builtin(isinf) */
358-
#endif /* __clang__ && !__cplusplus*/
362+
#endif /* __clang__ && !__cplusplus */
359363
#endif /* !HAVE_ISINF */
360364

361365
#ifndef HAVE_MKDTEMP
@@ -403,7 +407,7 @@ extern void srandom(unsigned int seed);
403407
#ifndef HAVE_DLOPEN
404408
extern void *dlopen(const char *file, int mode);
405409
extern void *dlsym(void *handle, const char *symbol);
406-
extern int dlclose(void *handle);
410+
extern int dlclose(void *handle);
407411
extern char *dlerror(void);
408412
#endif
409413

src/include/port/win32_port.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -322,8 +322,8 @@ extern int pgwin32_safestat(const char *path, struct stat *buf);
322322
* Supplement to <errno.h>.
323323
*
324324
* We redefine network-related Berkeley error symbols as the corresponding WSA
325-
* constants. This allows elog.c to recognize them as being in the Winsock
326-
* error code range and pass them off to pgwin32_socket_strerror(), since
325+
* constants. This allows strerror.c to recognize them as being in the Winsock
326+
* error code range and pass them off to win32_socket_strerror(), since
327327
* Windows' version of plain strerror() won't cope. Note that this will break
328328
* if these names are used for anything else besides Windows Sockets errors.
329329
* See TranslateSocketError() when changing this list.
@@ -456,8 +456,6 @@ int pgwin32_connect(SOCKET s, const struct sockaddr *name, int namelen);
456456
int pgwin32_select(int nfds, fd_set *readfs, fd_set *writefds, fd_set *exceptfds, const struct timeval *timeout);
457457
int pgwin32_recv(SOCKET s, char *buf, int len, int flags);
458458
int pgwin32_send(SOCKET s, const void *buf, int len, int flags);
459-
460-
const char *pgwin32_socket_strerror(int err);
461459
int pgwin32_waitforsinglesocket(SOCKET s, int what, int timeout);
462460

463461
extern int pgwin32_noblock;

src/interfaces/ecpg/compatlib/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22
/blibecpg_compatdll.def
33
/exports.list
44
/snprintf.c
5+
/strerror.c
56
/strnlen.c

0 commit comments

Comments
 (0)