Skip to content
This repository
Browse code

use FormatMessage for winsock errors

  • Loading branch information...
commit 0c6ec5d816189805c6fafdf385b171cbc3f67ff3 1 parent 7296512
Patrick Pelletier ppelleti authored

Showing 3 changed files with 130 additions and 68 deletions. Show diff stats Hide diff stats

  1. +2 0  event.c
  2. +1 0  evthread-internal.h
  3. +127 68 evutil.c
2  event.c
@@ -3468,6 +3468,8 @@ event_global_setup_locks_(const int enable_locks)
3468 3468 #endif
3469 3469 if (evsig_global_setup_locks_(enable_locks) < 0)
3470 3470 return -1;
  3471 + if (evutil_global_setup_locks_(enable_locks) < 0)
  3472 + return -1;
3471 3473 if (evutil_secure_rng_global_setup_locks_(enable_locks) < 0)
3472 3474 return -1;
3473 3475 return 0;
1  evthread-internal.h
@@ -373,6 +373,7 @@ void *evthread_setup_global_lock_(void *lock_, unsigned locktype,
373 373
374 374 int event_global_setup_locks_(const int enable_locks);
375 375 int evsig_global_setup_locks_(const int enable_locks);
  376 +int evutil_global_setup_locks_(const int enable_locks);
376 377 int evutil_secure_rng_global_setup_locks_(const int enable_locks);
377 378
378 379 #endif
195 evutil.c
@@ -81,6 +81,7 @@
81 81 #include "util-internal.h"
82 82 #include "log-internal.h"
83 83 #include "mm-internal.h"
  84 +#include "evthread-internal.h"
84 85
85 86 #include "strlcpy-internal.h"
86 87 #include "ipv6-internal.h"
@@ -1597,80 +1598,137 @@ evutil_gai_strerror(int err)
1597 1598 }
1598 1599
1599 1600 #ifdef _WIN32
1600   -#define E(code, s) { code, (s " [" #code " ]") }
1601   -static struct { int code; const char *msg; } windows_socket_errors[] = {
1602   - E(WSAEINTR, "Interrupted function call"),
1603   - E(WSAEACCES, "Permission denied"),
1604   - E(WSAEFAULT, "Bad address"),
1605   - E(WSAEINVAL, "Invalid argument"),
1606   - E(WSAEMFILE, "Too many open files"),
1607   - E(WSAEWOULDBLOCK, "Resource temporarily unavailable"),
1608   - E(WSAEINPROGRESS, "Operation now in progress"),
1609   - E(WSAEALREADY, "Operation already in progress"),
1610   - E(WSAENOTSOCK, "Socket operation on nonsocket"),
1611   - E(WSAEDESTADDRREQ, "Destination address required"),
1612   - E(WSAEMSGSIZE, "Message too long"),
1613   - E(WSAEPROTOTYPE, "Protocol wrong for socket"),
1614   - E(WSAENOPROTOOPT, "Bad protocol option"),
1615   - E(WSAEPROTONOSUPPORT, "Protocol not supported"),
1616   - E(WSAESOCKTNOSUPPORT, "Socket type not supported"),
1617   - /* What's the difference between NOTSUPP and NOSUPPORT? :) */
1618   - E(WSAEOPNOTSUPP, "Operation not supported"),
1619   - E(WSAEPFNOSUPPORT, "Protocol family not supported"),
1620   - E(WSAEAFNOSUPPORT, "Address family not supported by protocol family"),
1621   - E(WSAEADDRINUSE, "Address already in use"),
1622   - E(WSAEADDRNOTAVAIL, "Cannot assign requested address"),
1623   - E(WSAENETDOWN, "Network is down"),
1624   - E(WSAENETUNREACH, "Network is unreachable"),
1625   - E(WSAENETRESET, "Network dropped connection on reset"),
1626   - E(WSAECONNABORTED, "Software caused connection abort"),
1627   - E(WSAECONNRESET, "Connection reset by peer"),
1628   - E(WSAENOBUFS, "No buffer space available"),
1629   - E(WSAEISCONN, "Socket is already connected"),
1630   - E(WSAENOTCONN, "Socket is not connected"),
1631   - E(WSAESHUTDOWN, "Cannot send after socket shutdown"),
1632   - E(WSAETIMEDOUT, "Connection timed out"),
1633   - E(WSAECONNREFUSED, "Connection refused"),
1634   - E(WSAEHOSTDOWN, "Host is down"),
1635   - E(WSAEHOSTUNREACH, "No route to host"),
1636   - E(WSAEPROCLIM, "Too many processes"),
1637   -
1638   - /* Yes, some of these start with WSA, not WSAE. No, I don't know why. */
1639   - E(WSASYSNOTREADY, "Network subsystem is unavailable"),
1640   - E(WSAVERNOTSUPPORTED, "Winsock.dll out of range"),
1641   - E(WSANOTINITIALISED, "Successful WSAStartup not yet performed"),
1642   - E(WSAEDISCON, "Graceful shutdown now in progress"),
1643   -#ifdef WSATYPE_NOT_FOUND
1644   - E(WSATYPE_NOT_FOUND, "Class type not found"),
1645   -#endif
1646   - E(WSAHOST_NOT_FOUND, "Host not found"),
1647   - E(WSATRY_AGAIN, "Nonauthoritative host not found"),
1648   - E(WSANO_RECOVERY, "This is a nonrecoverable error"),
1649   - E(WSANO_DATA, "Valid name, no data record of requested type)"),
1650   -
1651   - /* There are some more error codes whose numeric values are marked
1652   - * <b>OS dependent</b>. They start with WSA_, apparently for the same
1653   - * reason that practitioners of some craft traditions deliberately
1654   - * introduce imperfections into their baskets and rugs "to allow the
1655   - * evil spirits to escape." If we catch them, then our binaries
1656   - * might not report consistent results across versions of Windows.
1657   - * Thus, I'm going to let them all fall through.
1658   - */
1659   - { -1, NULL },
  1601 +/* destructively remove a trailing line terminator from s */
  1602 +static void
  1603 +chomp (char *s)
  1604 +{
  1605 + size_t len;
  1606 + if (s && (len = strlen (s)) > 0 && s[len - 1] == '\n') {
  1607 + s[--len] = 0;
  1608 + if (len > 0 && s[len - 1] == '\r')
  1609 + s[--len] = 0;
  1610 + }
  1611 +}
  1612 +
  1613 +/* FormatMessage returns allocated strings, but evutil_socket_error_to_string
  1614 + * is supposed to return a string which is good indefinitely without having
  1615 + * to be freed. To make this work without leaking memory, we cache the
  1616 + * string the first time FormatMessage is called on a particular error
  1617 + * code, and then return the cached string on subsequent calls with the
  1618 + * same code. The strings aren't freed until libevent_global_shutdown
  1619 + * (or never). We use a linked list to cache the errors, because we
  1620 + * only expect there to be a few dozen, and that should be fast enough.
  1621 + */
  1622 +
  1623 +struct cached_sock_errs {
  1624 + DWORD code;
  1625 + char *msg; /* allocated with LocalAlloc; free with LocalFree */
  1626 + struct cached_sock_errs *next;
1660 1627 };
1661   -#undef E
  1628 +
  1629 +#ifndef EVENT__DISABLE_THREAD_SUPPORT
  1630 +static void *windows_socket_errors_lock_ = NULL;
  1631 +#endif
  1632 +
  1633 +static struct cached_sock_errs *windows_socket_errors;
  1634 +
1662 1635 /** Equivalent to strerror, but for windows socket errors. */
1663 1636 const char *
1664 1637 evutil_socket_error_to_string(int errcode)
1665 1638 {
1666   - /* XXXX Is there really no built-in function to do this? */
1667   - int i;
1668   - for (i=0; windows_socket_errors[i].code >= 0; ++i) {
1669   - if (errcode == windows_socket_errors[i].code)
1670   - return windows_socket_errors[i].msg;
1671   - }
1672   - return strerror(errcode);
  1639 + struct cached_sock_errs *errs, *newerr;
  1640 + char *msg = NULL;
  1641 +
  1642 + EVLOCK_LOCK(windows_socket_errors_lock_, 0);
  1643 +
  1644 + for (errs = windows_socket_errors; errs != NULL; errs = errs->next)
  1645 + if (errs->code == errcode) {
  1646 + msg = errs->msg;
  1647 + goto done;
  1648 + }
  1649 +
  1650 + if (0 != FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
  1651 + FORMAT_MESSAGE_IGNORE_INSERTS |
  1652 + FORMAT_MESSAGE_ALLOCATE_BUFFER,
  1653 + NULL, errcode, 0, (LPTSTR)&msg, 0, NULL))
  1654 + chomp (msg); /* because message has trailing newline */
  1655 + else {
  1656 + size_t len = 50;
  1657 + /* use LocalAlloc because FormatMessage does */
  1658 + msg = LocalAlloc(LMEM_FIXED, len);
  1659 + if (!msg) {
  1660 + msg = "winsock error";
  1661 + goto done;
  1662 + }
  1663 + evutil_snprintf(msg, len, "winsock error 0x%08x", errcode);
  1664 + }
  1665 +
  1666 + newerr = (struct cached_sock_errs *)
  1667 + mm_malloc(sizeof (struct cached_sock_errs));
  1668 +
  1669 + if (!newerr) {
  1670 + LocalFree(msg);
  1671 + msg = "winsock error";
  1672 + goto done;
  1673 + }
  1674 +
  1675 + newerr->code = errcode;
  1676 + newerr->msg = msg;
  1677 + newerr->next = windows_socket_errors;
  1678 + windows_socket_errors = newerr;
  1679 +
  1680 + done:
  1681 + EVLOCK_UNLOCK(windows_socket_errors_lock_, 0);
  1682 +
  1683 + return msg;
1673 1684 }
  1685 +
  1686 +#ifndef EVENT__DISABLE_THREAD_SUPPORT
  1687 +int
  1688 +evutil_global_setup_locks_(const int enable_locks)
  1689 +{
  1690 + EVTHREAD_SETUP_GLOBAL_LOCK(windows_socket_errors_lock_, 0);
  1691 + return 0;
  1692 +}
  1693 +#endif
  1694 +
  1695 +static void
  1696 +evutil_free_sock_err_globals(void)
  1697 +{
  1698 + struct cached_sock_errs *errs, *tofree;
  1699 +
  1700 + for (errs = windows_socket_errors; errs != NULL; ) {
  1701 + LocalFree (errs->msg);
  1702 + tofree = errs;
  1703 + errs = errs->next;
  1704 + mm_free (tofree);
  1705 + }
  1706 +
  1707 + windows_socket_errors = NULL;
  1708 +
  1709 +#ifndef EVENT__DISABLE_THREAD_SUPPORT
  1710 + if (windows_socket_errors_lock_ != NULL) {
  1711 + EVTHREAD_FREE_LOCK(windows_socket_errors_lock_, 0);
  1712 + windows_socket_errors_lock_ = NULL;
  1713 + }
  1714 +#endif
  1715 +}
  1716 +
  1717 +#else
  1718 +
  1719 +#ifndef EVENT__DISABLE_THREAD_SUPPORT
  1720 +int
  1721 +evutil_global_setup_locks_(const int enable_locks)
  1722 +{
  1723 + return 0;
  1724 +}
  1725 +#endif
  1726 +
  1727 +static void
  1728 +evutil_free_sock_err_globals(void)
  1729 +{
  1730 +}
  1731 +
1674 1732 #endif
1675 1733
1676 1734 int
@@ -2529,4 +2587,5 @@ void
2529 2587 evutil_free_globals_(void)
2530 2588 {
2531 2589 evutil_free_secure_rng_globals_();
  2590 + evutil_free_sock_err_globals();
2532 2591 }

0 comments on commit 0c6ec5d

Please sign in to comment.
Something went wrong with that request. Please try again.