Unverified Commit 550db18e authored by Dominik Charousset's avatar Dominik Charousset Committed by GitHub

Merge pull request #772

Set CLOEXEC flag on socket/accept/pipe calls
parents ddda3d9e 69756788
......@@ -101,7 +101,11 @@ namespace detail {
std::vector<iface_info> get_mac_addresses() {
// get a socket handle
int sck = socket(AF_INET, SOCK_DGRAM, 0);
int socktype = SOCK_DGRAM;
#ifdef SOCK_CLOEXEC
socktype |= SOCK_CLOEXEC;
#endif
int sck = socket(AF_INET, socktype, 0);
if (sck < 0) {
perror("socket");
return {};
......
......@@ -83,6 +83,11 @@ std::string last_socket_error_as_string();
/// and the latter is the write handle.
std::pair<native_socket, native_socket> create_pipe();
/// Sets fd to be inherited by child processes if `new_value == true`
/// or not if `new_value == false`. Not implemented on Windows.
/// throws `network_error` on error
expected<void> child_process_inherit(native_socket fd, bool new_value);
/// Sets fd to nonblocking if `set_nonblocking == true`
/// or to blocking if `set_nonblocking == false`
/// throws `network_error` on error
......
......@@ -776,8 +776,12 @@ new_tcp_connection(const std::string& host, uint16_t port,
}
auto proto = res->second;
CAF_ASSERT(proto == ipv4 || proto == ipv6);
int socktype = SOCK_STREAM;
#ifdef SOCK_CLOEXEC
socktype |= SOCK_CLOEXEC;
#endif
CALL_CFUN(fd, detail::cc_valid_socket, "socket",
socket(proto == ipv4 ? AF_INET : AF_INET6, SOCK_STREAM, 0));
socket(proto == ipv4 ? AF_INET : AF_INET6, socktype, 0));
detail::socket_guard sguard(fd);
if (proto == ipv6) {
if (ip_connect<AF_INET6>(fd, res->first, port)) {
......@@ -828,7 +832,11 @@ expected<native_socket> new_ip_acceptor_impl(uint16_t port, const char* addr,
bool reuse_addr, bool any) {
static_assert(Family == AF_INET || Family == AF_INET6, "invalid family");
CAF_LOG_TRACE(CAF_ARG(port) << ", addr = " << (addr ? addr : "nullptr"));
CALL_CFUN(fd, detail::cc_valid_socket, "socket", socket(Family, SockType, 0));
int socktype = SockType;
#ifdef SOCK_CLOEXEC
socktype |= SOCK_CLOEXEC;
#endif
CALL_CFUN(fd, detail::cc_valid_socket, "socket", socket(Family, socktype, 0));
// sguard closes the socket in case of exception
detail::socket_guard sguard{fd};
if (reuse_addr) {
......
......@@ -125,6 +125,16 @@ namespace network {
return strerror(errno);
}
expected<void> child_process_inherit(native_socket fd, bool new_value) {
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(new_value));
// read flags for fd
CALL_CFUN(rf, detail::cc_not_minus1, "fcntl", fcntl(fd, F_GETFD));
// calculate and set new flags
auto wf = (! new_value) ? (rf | FD_CLOEXEC) : (rf & (~(FD_CLOEXEC)));
CALL_CFUN(set_res, detail::cc_not_minus1, "fcntl", fcntl(fd, F_SETFD, wf));
return unit;
}
expected<void> nonblocking(native_socket fd, bool new_value) {
CAF_LOG_TRACE(CAF_ARG(fd) << CAF_ARG(new_value));
// read flags for fd
......@@ -156,6 +166,9 @@ namespace network {
perror("pipe");
exit(EXIT_FAILURE);
}
// note pipe2 is better to avoid races in setting CLOEXEC (but not posix)
child_process_inherit(pipefds[0], false);
child_process_inherit(pipefds[1], false);
return {pipefds[0], pipefds[1]};
}
......@@ -197,6 +210,11 @@ namespace network {
return result;
}
expected<void> child_process_inherit(native_socket fd, bool new_value) {
// nop; FIXME: possible to implement via SetHandleInformation ?
return unit;
}
expected<void> nonblocking(native_socket fd, bool new_value) {
u_long mode = new_value ? 1 : 0;
CALL_CFUN(res, detail::cc_zero, "ioctlsocket",
......
......@@ -71,6 +71,8 @@ bool tcp::try_accept(native_socket& result, native_socket fd) {
std::memset(&addr, 0, sizeof(addr));
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();
......
......@@ -80,6 +80,8 @@ struct ssl_policy {
memset(&addr, 0, sizeof(addr));
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();
......
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