in demo_example/asio/asio/detail/impl/socket_ops.ipp [294:355]
int close(socket_type s, state_type& state,
bool destruction, asio::error_code& ec)
{
int result = 0;
if (s != invalid_socket)
{
// We don't want the destructor to block, so set the socket to linger in
// the background. If the user doesn't like this behaviour then they need
// to explicitly close the socket.
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);
}
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = ::closesocket(s);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = ::close(s);
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
get_last_error(ec, result != 0);
if (result != 0
&& (ec == asio::error::would_block
|| ec == asio::error::try_again))
{
// According to UNIX Network Programming Vol. 1, it is possible for
// close() to fail with EWOULDBLOCK under certain circumstances. What
// isn't clear is the state of the descriptor after this error. The one
// current OS where this behaviour is seen, Windows, says that the socket
// remains open. Therefore we'll put the descriptor back into blocking
// mode and have another attempt at closing it.
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
ioctl_arg_type arg = 0;
::ioctlsocket(s, FIONBIO, &arg);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
# if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
int flags = ::fcntl(s, F_GETFL, 0);
if (flags >= 0)
::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);
# else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
ioctl_arg_type arg = 0;
::ioctl(s, FIONBIO, &arg);
# endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
state &= ~non_blocking;
#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = ::closesocket(s);
#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
result = ::close(s);
#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)
get_last_error(ec, result != 0);
}
}
return result;
}