summaryrefslogtreecommitdiffstats
path: root/ext
diff options
context:
space:
mode:
authorJINMEI Tatuya <jinmei@isc.org>2012-02-27 00:53:40 +0100
committerJINMEI Tatuya <jinmei@isc.org>2012-02-27 00:53:40 +0100
commitcf00216570a36d2e3e688b197deea781bfbe7d8d (patch)
treeaa85a29dd7640844d519df795dcd225aa1e0aaf6 /ext
parent[asiofix] imported a bug fix in ASIO 1.5.1: (diff)
downloadkea-cf00216570a36d2e3e688b197deea781bfbe7d8d.tar.xz
kea-cf00216570a36d2e3e688b197deea781bfbe7d8d.zip
[asiofix] imoprted a fix in ASIO 1.5.2:
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.
Diffstat (limited to 'ext')
-rw-r--r--ext/asio/asio/detail/impl/socket_ops.ipp36
1 files changed, 18 insertions, 18 deletions
diff --git a/ext/asio/asio/detail/impl/socket_ops.ipp b/ext/asio/asio/detail/impl/socket_ops.ipp
index 66006ea37a..a1b0ec6a89 100644
--- a/ext/asio/asio/detail/impl/socket_ops.ipp
+++ b/ext/asio/asio/detail/impl/socket_ops.ipp
@@ -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)