]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[asiofix] imoprted a fix in ASIO 1.5.2:
authorJINMEI Tatuya <jinmei@isc.org>
Sun, 26 Feb 2012 23:53:40 +0000 (15:53 -0800)
committerJINMEI Tatuya <jinmei@isc.org>
Sun, 26 Feb 2012 23:53:40 +0000 (15:53 -0800)
https://sourceforge.net/projects/asio/files/asio/1.5.2%20%28Development%29/
* Cleaned up the handling of errors reported by the `close()` system call. In particular, assume that most operating systems won't have `close()` fail with `EWOULDBLOCK`, but if it does then set the blocking mode and restart the call. If any other error occurs, assume the descriptor is closed.

Previous versions uncoditionally made sockets blocking on close(), which
was propagated to other processes that share the same socket.
It (could) subsequently cause a hangup-like situation.

ext/asio/asio/detail/impl/socket_ops.ipp

index 66006ea37a07ccfc9e93970daba36e04a765c179..a1b0ec6a891938c6f998a5dab2774605a657e2cf 100644 (file)
@@ -282,15 +282,26 @@ int close(socket_type s, state_type& state,
   int result = 0;
   if (s != invalid_socket)
   {
-#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-    if ((state & non_blocking) && (state & user_set_linger))
+    if (destruction && (state & user_set_linger))
     {
-      ioctl_arg_type arg = 0;
-      ::ioctlsocket(s, FIONBIO, &arg);
-      state &= ~non_blocking;
+      ::linger opt;
+      opt.l_onoff = 0;
+      opt.l_linger = 0;
+      asio::error_code ignored_ec;
+      socket_ops::setsockopt(s, state, SOL_SOCKET,
+          SO_LINGER, &opt, sizeof(opt), ignored_ec);
     }
+
+    clear_last_error();
+#if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    result = error_wrapper(::closesocket(s), ec);
 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-    if (state & non_blocking)
+    result = error_wrapper(::close(s), ec);
+#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+
+    if (result != 0
+        && (ec == asio::error::would_block
+          || ec == asio::error::try_again))
     {
 #if defined(__SYMBIAN32__)
       int flags = ::fcntl(s, F_GETFL, 0);
@@ -301,18 +312,6 @@ int close(socket_type s, state_type& state,
       ::ioctl(s, FIONBIO, &arg);
 #endif // defined(__SYMBIAN32__)
       state &= ~non_blocking;
-    }
-#endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
-
-    if (destruction && (state & user_set_linger))
-    {
-      ::linger opt;
-      opt.l_onoff = 0;
-      opt.l_linger = 0;
-      asio::error_code ignored_ec;
-      socket_ops::setsockopt(s, state, SOL_SOCKET,
-          SO_LINGER, &opt, sizeof(opt), ignored_ec);
-    }
 
     clear_last_error();
 #if defined(BOOST_WINDOWS) || defined(__CYGWIN__)
@@ -320,6 +319,7 @@ int close(socket_type s, state_type& state,
 #else // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
     result = error_wrapper(::close(s), ec);
 #endif // defined(BOOST_WINDOWS) || defined(__CYGWIN__)
+    }
   }
 
   if (result == 0)