Commit cc825f70 authored by Dominik Charousset's avatar Dominik Charousset

Suppress SIGPIPE events on all sockets

parent 3e51f9b8
...@@ -140,19 +140,22 @@ using native_socket_acceptor = native_socket; ...@@ -140,19 +140,22 @@ using native_socket_acceptor = native_socket;
/// Returns the last socket error as human-readable string. /// Returns the last socket error as human-readable string.
std::string last_socket_error_as_string(); std::string last_socket_error_as_string();
/// Creates two connected sockets. The former is the read handle
/// and the latter is the write handle.
std::pair<native_socket, native_socket> create_pipe();
/// Sets fd to nonblocking if `set_nonblocking == true` /// Sets fd to nonblocking if `set_nonblocking == true`
/// or to blocking if `set_nonblocking == false` /// or to blocking if `set_nonblocking == false`
/// throws `network_error` on error /// throws `network_error` on error
void nonblocking(native_socket fd, bool new_value); void nonblocking(native_socket fd, bool new_value);
/// Creates two connected sockets. The former is the read handle /// Enables or disables Nagle's algorithm on `fd`.
/// and the latter is the write handle.
std::pair<native_socket, native_socket> create_pipe();
/// Returns true if `fd` is configured as nodelay socket.
/// @throws network_error /// @throws network_error
void tcp_nodelay(native_socket fd, bool new_value); void tcp_nodelay(native_socket fd, bool new_value);
/// Enables or disables `SIGPIPE` events from `fd`.
void allow_sigpipe(native_socket fs, bool new_value);
/// Throws `network_error` if `result` is invalid. /// Throws `network_error` if `result` is invalid.
void handle_write_result(ssize_t result); void handle_write_result(ssize_t result);
......
...@@ -50,14 +50,6 @@ using std::string; ...@@ -50,14 +50,6 @@ using std::string;
namespace { namespace {
#if defined(CAF_MACOS) || defined(CAF_IOS)
constexpr int no_sigpipe_flag = SO_NOSIGPIPE;
#elif defined(CAF_WINDOWS)
constexpr int no_sigpipe_flag = 0; // does not exist on Windows
#else // BSD, Linux or Android
constexpr int no_sigpipe_flag = MSG_NOSIGNAL;
#endif
// safe ourselves some typing // safe ourselves some typing
constexpr auto ipv4 = caf::io::network::protocol::ipv4; constexpr auto ipv4 = caf::io::network::protocol::ipv4;
constexpr auto ipv6 = caf::io::network::protocol::ipv6; constexpr auto ipv6 = caf::io::network::protocol::ipv6;
...@@ -125,6 +117,11 @@ uint16_t port_of_fd(native_socket fd); ...@@ -125,6 +117,11 @@ uint16_t port_of_fd(native_socket fd);
ccall(cc_not_minus1, "cannot set flags", fcntl, fd, F_SETFL, wf); ccall(cc_not_minus1, "cannot set flags", fcntl, fd, F_SETFL, wf);
} }
void allow_sigpipe(native_socket fd, bool new_value) {
int value = new_value ? 0 : 1;
setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &value, sizeof(value));
}
std::pair<native_socket, native_socket> create_pipe() { std::pair<native_socket, native_socket> create_pipe() {
int pipefds[2]; int pipefds[2];
if (pipe(pipefds) != 0) { if (pipe(pipefds) != 0) {
...@@ -165,6 +162,10 @@ uint16_t port_of_fd(native_socket fd); ...@@ -165,6 +162,10 @@ uint16_t port_of_fd(native_socket fd);
ccall(cc_zero, "unable to set FIONBIO", ioctlsocket, fd, FIONBIO, &mode); ccall(cc_zero, "unable to set FIONBIO", ioctlsocket, fd, FIONBIO, &mode);
} }
void allow_sigpipe(native_socket, bool) {
// nop; SIGPIPE does not exist on Windows
}
/**************************************************************************\ /**************************************************************************\
* Based on work of others; * * Based on work of others; *
* original header: * * original header: *
...@@ -590,7 +591,7 @@ void default_multiplexer::wr_dispatch_request(runnable* ptr) { ...@@ -590,7 +591,7 @@ void default_multiplexer::wr_dispatch_request(runnable* ptr) {
// on windows, we actually have sockets, otherwise we have file handles // on windows, we actually have sockets, otherwise we have file handles
# ifdef CAF_WINDOWS # ifdef CAF_WINDOWS
auto res = ::send(pipe_.second, reinterpret_cast<socket_send_ptr>(&ptrval), auto res = ::send(pipe_.second, reinterpret_cast<socket_send_ptr>(&ptrval),
sizeof(ptrval), no_sigpipe_flag); sizeof(ptrval), 0);
# else # else
auto res = ::write(pipe_.second, &ptrval, sizeof(ptrval)); auto res = ::write(pipe_.second, &ptrval, sizeof(ptrval));
# endif # endif
...@@ -847,7 +848,8 @@ default_multiplexer::new_tcp_doorman(uint16_t port, const char* in, ...@@ -847,7 +848,8 @@ default_multiplexer::new_tcp_doorman(uint16_t port, const char* in,
res.second}; res.second};
} }
void default_multiplexer::assign_tcp_doorman(abstract_broker* ptr, accept_handle hdl) { void default_multiplexer::assign_tcp_doorman(abstract_broker* ptr,
accept_handle hdl) {
add_tcp_doorman(ptr, static_cast<native_socket>(hdl.id())); add_tcp_doorman(ptr, static_cast<native_socket>(hdl.id()));
} }
...@@ -903,8 +905,7 @@ bool read_some(size_t& result, native_socket fd, void* buf, size_t len) { ...@@ -903,8 +905,7 @@ bool read_some(size_t& result, native_socket fd, void* buf, size_t len) {
bool write_some(size_t& result, native_socket fd, const void* buf, size_t len) { bool write_some(size_t& result, native_socket fd, const void* buf, size_t len) {
CAF_LOGF_TRACE(CAF_ARG(fd) << ", " << CAF_ARG(len)); CAF_LOGF_TRACE(CAF_ARG(fd) << ", " << CAF_ARG(len));
auto sres = ::send(fd, reinterpret_cast<socket_send_ptr>(buf), auto sres = ::send(fd, reinterpret_cast<socket_send_ptr>(buf), len, 0);
len, no_sigpipe_flag);
CAF_LOGF_DEBUG("tried to write " << len << " bytes to socket " << fd CAF_LOGF_DEBUG("tried to write " << len << " bytes to socket " << fd
<< ", send returned " << sres); << ", send returned " << sres);
if (is_error(sres, true)) if (is_error(sres, true))
...@@ -945,9 +946,10 @@ default_socket::default_socket(default_multiplexer& ref, native_socket sockfd) ...@@ -945,9 +946,10 @@ default_socket::default_socket(default_multiplexer& ref, native_socket sockfd)
fd_(sockfd) { fd_(sockfd) {
CAF_LOG_TRACE(CAF_ARG(sockfd)); CAF_LOG_TRACE(CAF_ARG(sockfd));
if (sockfd != invalid_native_socket) { if (sockfd != invalid_native_socket) {
// enable nonblocking IO & disable Nagle's algorithm // enable nonblocking IO, disable Nagle's algorithm, and suppress SIGPIPE
nonblocking(fd_, true); nonblocking(fd_, true);
tcp_nodelay(fd_, true); tcp_nodelay(fd_, true);
allow_sigpipe(fd_, false);
} }
} }
......
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