Browse Source

fix #342: get errno before closesocket

ithewei 2 years ago
parent
commit
a9c6842658
1 changed files with 15 additions and 13 deletions
  1. 15 13
      base/hsocket.c

+ 15 - 13
base/hsocket.c

@@ -20,8 +20,9 @@ void WSADeinit() {
 }
 #endif
 
-static inline int socket_errno_negative() {
+static inline int socket_errno_negative(int sockfd) {
     int err = socket_errno();
+    if (sockfd >= 0) close(sockfd);
     return err > 0 ? -err : -1;
 }
 
@@ -177,7 +178,7 @@ static int sockaddr_bind(sockaddr_u* localaddr, int type) {
     int sockfd = socket(localaddr->sa.sa_family, type, 0);
     if (sockfd < 0) {
         perror("socket");
-        return socket_errno_negative();
+        goto error;
     }
 
 #ifdef OS_UNIX
@@ -192,47 +193,48 @@ static int sockaddr_bind(sockaddr_u* localaddr, int type) {
 
     return sockfd;
 error:
-    closesocket(sockfd);
-    return socket_errno_negative();
+    return socket_errno_negative(sockfd);
 }
 
 static int sockaddr_connect(sockaddr_u* peeraddr, int nonblock) {
     // socket -> nonblocking -> connect
+    int ret = 0;
     int connfd = socket(peeraddr->sa.sa_family, SOCK_STREAM, 0);
     if (connfd < 0) {
         perror("socket");
-        return socket_errno_negative();
+        goto error;
     }
 
     if (nonblock) {
         nonblocking(connfd);
     }
 
-    int ret = connect(connfd, &peeraddr->sa, sockaddr_len(peeraddr));
+    ret = connect(connfd, &peeraddr->sa, sockaddr_len(peeraddr));
 #ifdef OS_WIN
     if (ret < 0 && socket_errno() != WSAEWOULDBLOCK) {
 #else
     if (ret < 0 && socket_errno() != EINPROGRESS) {
 #endif
         // perror("connect");
-        closesocket(connfd);
-        return socket_errno_negative();
+        goto error;
     }
+
     return connfd;
+error:
+    return socket_errno_negative(connfd);
 }
 
 static int ListenFD(int sockfd) {
     if (sockfd < 0) return sockfd;
     if (listen(sockfd, SOMAXCONN) < 0) {
         perror("listen");
-        closesocket(sockfd);
-        return socket_errno_negative();
+        return socket_errno_negative(sockfd);
     }
     return sockfd;
 }
 
 static int ConnectFDTimeout(int connfd, int ms) {
-    int err;
+    int err = 0;
     socklen_t optlen = sizeof(err);
     struct timeval tv = { ms / 1000, (ms % 1000) * 1000 };
     fd_set writefds;
@@ -248,13 +250,13 @@ static int ConnectFDTimeout(int connfd, int ms) {
         goto error;
     }
     if (getsockopt(connfd, SOL_SOCKET, SO_ERROR, (char*)&err, &optlen) < 0 || err != 0) {
+        if (err != 0) errno = err;
         goto error;
     }
     blocking(connfd);
     return connfd;
 error:
-    closesocket(connfd);
-    return socket_errno_negative();
+    return socket_errno_negative(connfd);
 }
 
 int Bind(int port, const char* host, int type) {