int close()

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;
}