Skip to content

Commit 0394efc

Browse files
dschoGit for Windows Build Agent
authored and
Git for Windows Build Agent
committed
Merge pull request #2405 from dscho/mingw-setsockopt
Make sure `errno` is set when socket operations fail
2 parents dec2eb2 + fda7f04 commit 0394efc

File tree

1 file changed

+147
-10
lines changed

1 file changed

+147
-10
lines changed

compat/mingw.c

+147-10
Original file line numberDiff line numberDiff line change
@@ -2123,26 +2123,158 @@ static void ensure_socket_initialization(void)
21232123
initialized = 1;
21242124
}
21252125

2126+
static int winsock_error_to_errno(DWORD err)
2127+
{
2128+
switch (err) {
2129+
case WSAEINTR: return EINTR;
2130+
case WSAEBADF: return EBADF;
2131+
case WSAEACCES: return EACCES;
2132+
case WSAEFAULT: return EFAULT;
2133+
case WSAEINVAL: return EINVAL;
2134+
case WSAEMFILE: return EMFILE;
2135+
case WSAEWOULDBLOCK: return EWOULDBLOCK;
2136+
case WSAEINPROGRESS: return EINPROGRESS;
2137+
case WSAEALREADY: return EALREADY;
2138+
case WSAENOTSOCK: return ENOTSOCK;
2139+
case WSAEDESTADDRREQ: return EDESTADDRREQ;
2140+
case WSAEMSGSIZE: return EMSGSIZE;
2141+
case WSAEPROTOTYPE: return EPROTOTYPE;
2142+
case WSAENOPROTOOPT: return ENOPROTOOPT;
2143+
case WSAEPROTONOSUPPORT: return EPROTONOSUPPORT;
2144+
case WSAEOPNOTSUPP: return EOPNOTSUPP;
2145+
case WSAEAFNOSUPPORT: return EAFNOSUPPORT;
2146+
case WSAEADDRINUSE: return EADDRINUSE;
2147+
case WSAEADDRNOTAVAIL: return EADDRNOTAVAIL;
2148+
case WSAENETDOWN: return ENETDOWN;
2149+
case WSAENETUNREACH: return ENETUNREACH;
2150+
case WSAENETRESET: return ENETRESET;
2151+
case WSAECONNABORTED: return ECONNABORTED;
2152+
case WSAECONNRESET: return ECONNRESET;
2153+
case WSAENOBUFS: return ENOBUFS;
2154+
case WSAEISCONN: return EISCONN;
2155+
case WSAENOTCONN: return ENOTCONN;
2156+
case WSAETIMEDOUT: return ETIMEDOUT;
2157+
case WSAECONNREFUSED: return ECONNREFUSED;
2158+
case WSAELOOP: return ELOOP;
2159+
case WSAENAMETOOLONG: return ENAMETOOLONG;
2160+
case WSAEHOSTUNREACH: return EHOSTUNREACH;
2161+
case WSAENOTEMPTY: return ENOTEMPTY;
2162+
/* No errno equivalent; default to EIO */
2163+
case WSAESOCKTNOSUPPORT:
2164+
case WSAEPFNOSUPPORT:
2165+
case WSAESHUTDOWN:
2166+
case WSAETOOMANYREFS:
2167+
case WSAEHOSTDOWN:
2168+
case WSAEPROCLIM:
2169+
case WSAEUSERS:
2170+
case WSAEDQUOT:
2171+
case WSAESTALE:
2172+
case WSAEREMOTE:
2173+
case WSASYSNOTREADY:
2174+
case WSAVERNOTSUPPORTED:
2175+
case WSANOTINITIALISED:
2176+
case WSAEDISCON:
2177+
case WSAENOMORE:
2178+
case WSAECANCELLED:
2179+
case WSAEINVALIDPROCTABLE:
2180+
case WSAEINVALIDPROVIDER:
2181+
case WSAEPROVIDERFAILEDINIT:
2182+
case WSASYSCALLFAILURE:
2183+
case WSASERVICE_NOT_FOUND:
2184+
case WSATYPE_NOT_FOUND:
2185+
case WSA_E_NO_MORE:
2186+
case WSA_E_CANCELLED:
2187+
case WSAEREFUSED:
2188+
case WSAHOST_NOT_FOUND:
2189+
case WSATRY_AGAIN:
2190+
case WSANO_RECOVERY:
2191+
case WSANO_DATA:
2192+
case WSA_QOS_RECEIVERS:
2193+
case WSA_QOS_SENDERS:
2194+
case WSA_QOS_NO_SENDERS:
2195+
case WSA_QOS_NO_RECEIVERS:
2196+
case WSA_QOS_REQUEST_CONFIRMED:
2197+
case WSA_QOS_ADMISSION_FAILURE:
2198+
case WSA_QOS_POLICY_FAILURE:
2199+
case WSA_QOS_BAD_STYLE:
2200+
case WSA_QOS_BAD_OBJECT:
2201+
case WSA_QOS_TRAFFIC_CTRL_ERROR:
2202+
case WSA_QOS_GENERIC_ERROR:
2203+
case WSA_QOS_ESERVICETYPE:
2204+
case WSA_QOS_EFLOWSPEC:
2205+
case WSA_QOS_EPROVSPECBUF:
2206+
case WSA_QOS_EFILTERSTYLE:
2207+
case WSA_QOS_EFILTERTYPE:
2208+
case WSA_QOS_EFILTERCOUNT:
2209+
case WSA_QOS_EOBJLENGTH:
2210+
case WSA_QOS_EFLOWCOUNT:
2211+
#ifndef _MSC_VER
2212+
case WSA_QOS_EUNKNOWNPSOBJ:
2213+
#endif
2214+
case WSA_QOS_EPOLICYOBJ:
2215+
case WSA_QOS_EFLOWDESC:
2216+
case WSA_QOS_EPSFLOWSPEC:
2217+
case WSA_QOS_EPSFILTERSPEC:
2218+
case WSA_QOS_ESDMODEOBJ:
2219+
case WSA_QOS_ESHAPERATEOBJ:
2220+
case WSA_QOS_RESERVED_PETYPE:
2221+
default: return EIO;
2222+
}
2223+
}
2224+
2225+
/*
2226+
* On Windows, `errno` is a global macro to a function call.
2227+
* This makes it difficult to debug and single-step our mappings.
2228+
*/
2229+
static inline void set_wsa_errno(void)
2230+
{
2231+
DWORD wsa = WSAGetLastError();
2232+
int e = winsock_error_to_errno(wsa);
2233+
errno = e;
2234+
2235+
#ifdef DEBUG_WSA_ERRNO
2236+
fprintf(stderr, "winsock error: %d -> %d\n", wsa, e);
2237+
fflush(stderr);
2238+
#endif
2239+
}
2240+
2241+
static inline int winsock_return(int ret)
2242+
{
2243+
if (ret < 0)
2244+
set_wsa_errno();
2245+
2246+
return ret;
2247+
}
2248+
2249+
#define WINSOCK_RETURN(x) do { return winsock_return(x); } while (0)
2250+
21262251
#undef gethostname
21272252
int mingw_gethostname(char *name, int namelen)
21282253
{
2129-
ensure_socket_initialization();
2130-
return gethostname(name, namelen);
2254+
ensure_socket_initialization();
2255+
WINSOCK_RETURN(gethostname(name, namelen));
21312256
}
21322257

21332258
#undef gethostbyname
21342259
struct hostent *mingw_gethostbyname(const char *host)
21352260
{
2261+
struct hostent *ret;
2262+
21362263
ensure_socket_initialization();
2137-
return gethostbyname(host);
2264+
2265+
ret = gethostbyname(host);
2266+
if (!ret)
2267+
set_wsa_errno();
2268+
2269+
return ret;
21382270
}
21392271

21402272
#undef getaddrinfo
21412273
int mingw_getaddrinfo(const char *node, const char *service,
21422274
const struct addrinfo *hints, struct addrinfo **res)
21432275
{
21442276
ensure_socket_initialization();
2145-
return getaddrinfo(node, service, hints, res);
2277+
WINSOCK_RETURN(getaddrinfo(node, service, hints, res));
21462278
}
21472279

21482280
int mingw_socket(int domain, int type, int protocol)
@@ -2162,7 +2294,7 @@ int mingw_socket(int domain, int type, int protocol)
21622294
* in errno so that _if_ someone looks up the code somewhere,
21632295
* then it is at least the number that are usually listed.
21642296
*/
2165-
errno = WSAGetLastError();
2297+
set_wsa_errno();
21662298
return -1;
21672299
}
21682300
/* convert into a file descriptor */
@@ -2178,35 +2310,35 @@ int mingw_socket(int domain, int type, int protocol)
21782310
int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)
21792311
{
21802312
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2181-
return connect(s, sa, sz);
2313+
WINSOCK_RETURN(connect(s, sa, sz));
21822314
}
21832315

21842316
#undef bind
21852317
int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)
21862318
{
21872319
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2188-
return bind(s, sa, sz);
2320+
WINSOCK_RETURN(bind(s, sa, sz));
21892321
}
21902322

21912323
#undef setsockopt
21922324
int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)
21932325
{
21942326
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2195-
return setsockopt(s, lvl, optname, (const char*)optval, optlen);
2327+
WINSOCK_RETURN(setsockopt(s, lvl, optname, (const char*)optval, optlen));
21962328
}
21972329

21982330
#undef shutdown
21992331
int mingw_shutdown(int sockfd, int how)
22002332
{
22012333
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2202-
return shutdown(s, how);
2334+
WINSOCK_RETURN(shutdown(s, how));
22032335
}
22042336

22052337
#undef listen
22062338
int mingw_listen(int sockfd, int backlog)
22072339
{
22082340
SOCKET s = (SOCKET)_get_osfhandle(sockfd);
2209-
return listen(s, backlog);
2341+
WINSOCK_RETURN(listen(s, backlog));
22102342
}
22112343

22122344
#undef accept
@@ -2217,6 +2349,11 @@ int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)
22172349
SOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);
22182350
SOCKET s2 = accept(s1, sa, sz);
22192351

2352+
if (s2 == INVALID_SOCKET) {
2353+
set_wsa_errno();
2354+
return -1;
2355+
}
2356+
22202357
/* convert into a file descriptor */
22212358
if ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {
22222359
int err = errno;

0 commit comments

Comments
 (0)