Commit 41547a86 authored by Joseph Noir's avatar Joseph Noir

Fix disconnect issue on Windows

WSAGetLastError should be invoked right after Windows sockets
functions.
parent 3ecdb1c9
......@@ -339,8 +339,6 @@ namespace network {
presult = ::poll(pollset_.data(),
static_cast<nfds_t>(pollset_.size()), block ? -1 : 0);
# endif
CAF_LOG_DEBUG("poll() on" << pollset_.size()
<< "sockets reported" << presult << "event(s)");
if (presult < 0) {
switch (last_socket_error()) {
case EINTR: {
......@@ -362,6 +360,8 @@ namespace network {
}
continue; // rinse and repeat
}
CAF_LOG_DEBUG("poll() on" << pollset_.size()
<< "sockets reported" << presult << "event(s)");
if (presult == 0)
return false;
// scan pollset for events first, because we might alter pollset_
......
......@@ -20,6 +20,7 @@
#include <cstring>
#include "caf/io/network/native_socket.hpp"
#include "caf/logger.hpp"
#ifdef CAF_WINDOWS
......@@ -34,6 +35,7 @@ using caf::io::network::rw_state;
using caf::io::network::native_socket;
using caf::io::network::socket_size_type;
using caf::io::network::no_sigpipe_io_flag;
using caf::io::network::last_socket_error_as_string;
namespace caf {
namespace policy {
......@@ -43,11 +45,15 @@ rw_state tcp::read_some(size_t& result, native_socket fd, void* buf,
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len));
auto sres = ::recv(fd, reinterpret_cast<io::network::socket_recv_ptr>(buf),
len, no_sigpipe_io_flag);
CAF_LOG_DEBUG(CAF_ARG(len) << CAF_ARG(fd) << CAF_ARG(sres));
if (is_error(sres, true) || sres == 0) {
if (is_error(sres, true)) {
CAF_LOG_ERROR("recv failed:" << last_socket_error_as_string());
return rw_state::failure;
} else if (sres == 0) {
// recv returns 0 when the peer has performed an orderly shutdown
CAF_LOG_DEBUG("peer performed orderly shutdown" << CAF_ARG(fd));
return rw_state::failure;
}
CAF_LOG_DEBUG(CAF_ARG(len) << CAF_ARG(fd) << CAF_ARG(sres));
result = (sres > 0) ? static_cast<size_t>(sres) : 0;
return rw_state::success;
}
......@@ -57,9 +63,11 @@ rw_state tcp::write_some(size_t& result, native_socket fd, const void* buf,
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(len));
auto sres = ::send(fd, reinterpret_cast<io::network::socket_send_ptr>(buf),
len, no_sigpipe_io_flag);
CAF_LOG_DEBUG(CAF_ARG(len) << CAF_ARG(fd) << CAF_ARG(sres));
if (is_error(sres, true))
if (is_error(sres, true)) {
CAF_LOG_ERROR("send failed:" << last_socket_error_as_string());
return rw_state::failure;
}
CAF_LOG_DEBUG(CAF_ARG(len) << CAF_ARG(fd) << CAF_ARG(sres));
result = (sres > 0) ? static_cast<size_t>(sres) : 0;
return rw_state::success;
}
......@@ -72,14 +80,15 @@ bool tcp::try_accept(native_socket& result, native_socket fd) {
socket_size_type addrlen = sizeof(addr);
result = ::accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
// note accept4 is better to avoid races in setting CLOEXEC (but not posix)
child_process_inherit(result, false);
CAF_LOG_DEBUG(CAF_ARG(fd) << CAF_ARG(result));
if (result == invalid_native_socket) {
auto err = last_socket_error();
if (!would_block_or_temporarily_unavailable(err)) {
CAF_LOG_ERROR("accept failed:" << last_socket_error_as_string());
return false;
}
}
child_process_inherit(result, false);
CAF_LOG_DEBUG(CAF_ARG(fd) << CAF_ARG(result));
return true;
}
......
......@@ -18,6 +18,7 @@
#include "caf/policy/udp.hpp"
#include "caf/io/network/native_socket.hpp"
#include "caf/logger.hpp"
#ifdef CAF_WINDOWS
......@@ -32,6 +33,7 @@ using caf::io::network::ip_endpoint;
using caf::io::network::native_socket;
using caf::io::network::signed_size_type;
using caf::io::network::socket_size_type;
using caf::io::network::last_socket_error_as_string;
namespace caf {
namespace policy {
......@@ -44,7 +46,7 @@ bool udp::read_datagram(size_t& result, native_socket fd, void* buf,
auto sres = ::recvfrom(fd, static_cast<io::network::socket_recv_ptr>(buf),
buf_len, 0, ep.address(), &len);
if (is_error(sres, true)) {
CAF_LOG_ERROR("recvfrom returned" << CAF_ARG(sres));
CAF_LOG_ERROR("recvfrom failed:" << last_socket_error_as_string());
return false;
}
if (sres == 0)
......@@ -64,7 +66,7 @@ bool udp::write_datagram(size_t& result, native_socket fd, void* buf,
auto sres = ::sendto(fd, reinterpret_cast<io::network::socket_send_ptr>(buf),
buf_len, 0, ep.caddress(), len);
if (is_error(sres, true)) {
CAF_LOG_ERROR("sendto returned" << CAF_ARG(sres));
CAF_LOG_ERROR("sendto failed:" << last_socket_error_as_string());
return false;
}
result = (sres > 0) ? static_cast<size_t>(sres) : 0;
......
......@@ -81,13 +81,15 @@ struct ssl_policy {
caf::io::network::socket_size_type addrlen = sizeof(addr);
result = accept(fd, reinterpret_cast<sockaddr*>(&addr), &addrlen);
// note accept4 is better to avoid races in setting CLOEXEC (but not posix)
io::network::child_process_inherit(result, false);
CAF_LOG_DEBUG(CAF_ARG(fd) << CAF_ARG(result));
if (result == io::network::invalid_native_socket) {
auto err = io::network::last_socket_error();
if (!io::network::would_block_or_temporarily_unavailable(err))
CAF_LOG_ERROR("accept failed:"
<< io::network::last_socket_error_as_string());
return false;
}
io::network::child_process_inherit(result, false);
CAF_LOG_DEBUG(CAF_ARG(fd) << CAF_ARG(result));
return session_->try_accept(result);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment