Skip to content

Commit

Permalink
Fix macOS issue with SOCK_CLOEXEC (netdata#17151)
Browse files Browse the repository at this point in the history
* Fix macos issue with SOCK_CLOEXEC

* Code cleanup

* Fix SOCK_NONBLOCK not available

* Fix compilation error

* Code simplify

* Properly check return code
  • Loading branch information
stelfrag authored Mar 15, 2024
1 parent 460577b commit db63ab8
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 25 deletions.
8 changes: 7 additions & 1 deletion src/aclk/mqtt_websockets/mqtt_wss_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -583,12 +583,18 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c

if (client->sockfd > 0)
close(client->sockfd);
client->sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
client->sockfd = socket(AF_INET, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
if (client->sockfd < 0) {
mws_error(client->log, "Couldn't create socket()");
return -1;
}

#ifndef SOCK_CLOEXEC
int flags = fcntl(client->sockfd, F_GETFD);
if (flags != -1)
(void) fcntl(client->sockfd, F_SETFD, flags| FD_CLOEXEC);
#endif

int flag = 1;
int result = setsockopt(client->sockfd,
IPPROTO_TCP,
Expand Down
4 changes: 3 additions & 1 deletion src/libnetdata/log/journal.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,11 @@ int journal_direct_fd(const char *path) {
if(!is_path_unix_socket(path))
return -1;

int fd = socket(AF_UNIX, SOCK_DGRAM| SOCK_CLOEXEC, 0);
int fd = socket(AF_UNIX, SOCK_DGRAM| DEFAULT_SOCKET_FLAGS, 0);
if (fd < 0) return -1;

sock_setcloexec(fd);

struct sockaddr_un addr;
memset(&addr, 0, sizeof(struct sockaddr_un));
addr.sun_family = AF_UNIX;
Expand Down
51 changes: 37 additions & 14 deletions src/libnetdata/socket/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,16 @@ int sock_setreuse(int fd, int reuse) {
return ret;
}

void sock_setcloexec(int fd)
{
UNUSED(fd);
#ifndef SOCK_CLOEXEC
int flags = fcntl(fd, F_GETFD);
if (flags != -1)
(void) fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
#endif
}

int sock_setreuse_port(int fd, int reuse) {
int ret;

Expand Down Expand Up @@ -262,7 +272,7 @@ char *strdup_client_description(int family, const char *protocol, const char *ip
int create_listen_socket_unix(const char *path, int listen_backlog) {
int sock;

sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
sock = socket(AF_UNIX, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
if(sock < 0) {
nd_log(NDLS_DAEMON, NDLP_ERR,
"LISTENER: UNIX socket() on path '%s' failed.",
Expand All @@ -272,6 +282,7 @@ int create_listen_socket_unix(const char *path, int listen_backlog) {
}

sock_setnonblock(sock);
sock_setcloexec(sock);
sock_enlarge_in(sock);

struct sockaddr_un name;
Expand Down Expand Up @@ -316,18 +327,18 @@ int create_listen_socket_unix(const char *path, int listen_backlog) {
int create_listen_socket4(int socktype, const char *ip, uint16_t port, int listen_backlog) {
int sock;

sock = socket(AF_INET, socktype | SOCK_CLOEXEC, 0);
sock = socket(AF_INET, socktype | DEFAULT_SOCKET_FLAGS, 0);
if(sock < 0) {
nd_log(NDLS_DAEMON, NDLP_ERR,
"LISTENER: IPv4 socket() on ip '%s' port %d, socktype %d failed.",
ip, port, socktype);

return -1;
}

sock_setreuse(sock, 1);
sock_setreuse_port(sock, 0);
sock_setnonblock(sock);
sock_setcloexec(sock);
sock_enlarge_in(sock);

struct sockaddr_in name;
Expand Down Expand Up @@ -374,18 +385,18 @@ int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int p
int sock;
int ipv6only = 1;

sock = socket(AF_INET6, socktype | SOCK_CLOEXEC, 0);
sock = socket(AF_INET6, socktype | DEFAULT_SOCKET_FLAGS, 0);
if (sock < 0) {
nd_log(NDLS_DAEMON, NDLP_ERR,
"LISTENER: IPv6 socket() on ip '%s' port %d, socktype %d, failed.",
ip, port, socktype);

return -1;
}

sock_setreuse(sock, 1);
sock_setreuse_port(sock, 0);
sock_setnonblock(sock);
sock_setcloexec(sock);
sock_enlarge_in(sock);

/* IPv6 only */
Expand Down Expand Up @@ -781,7 +792,7 @@ int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
// timeout the timeout for establishing a connection

static inline int connect_to_unix(const char *path, struct timeval *timeout) {
int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
int fd = socket(AF_UNIX, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
if(fd == -1) {
nd_log(NDLS_DAEMON, NDLP_ERR,
"Failed to create UNIX socket() for '%s'",
Expand All @@ -797,6 +808,8 @@ static inline int connect_to_unix(const char *path, struct timeval *timeout) {
path);
}

sock_setcloexec(fd);

struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
Expand Down Expand Up @@ -894,14 +907,15 @@ int connect_to_this_ip46(int protocol, int socktype, const char *host, uint32_t
}
}

fd = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, ai->ai_protocol);
fd = socket(ai->ai_family, ai->ai_socktype | DEFAULT_SOCKET_FLAGS, ai->ai_protocol);
if(fd != -1) {
if(timeout) {
if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
nd_log(NDLS_DAEMON, NDLP_ERR,
"Failed to set timeout on the socket to ip '%s' port '%s'",
hostBfr, servBfr);
}
sock_setcloexec(fd);

errno = 0;
if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
Expand Down Expand Up @@ -1266,11 +1280,6 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {

if (fd < 0) return fd;

if (flags & SOCK_NONBLOCK) {
newflags |= O_NONBLOCK;
flags &= ~SOCK_NONBLOCK;
}

#ifdef SOCK_CLOEXEC
#ifdef O_CLOEXEC
if (flags & SOCK_CLOEXEC) {
Expand Down Expand Up @@ -1387,7 +1396,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
struct sockaddr_storage sadr;
socklen_t addrlen = sizeof(sadr);

int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags | SOCK_CLOEXEC);
int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags | DEFAULT_SOCKET_FLAGS);
if (likely(nfd >= 0)) {
if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize,
client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
Expand All @@ -1401,6 +1410,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
if (!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
strncpyz(client_ip, "localhost", ipsize);
}
sock_setcloexec(nfd);

#ifdef __FreeBSD__
if(((struct sockaddr *)&sadr)->sa_family == AF_LOCAL)
Expand Down Expand Up @@ -1785,12 +1795,25 @@ static int poll_process_new_tcp_connection(POLLJOB *p, POLLINFO *pi, struct poll
char client_port[NI_MAXSERV] = "";
char client_host[NI_MAXHOST] = "";

#ifdef SOCK_NONBLOCK
int flags = SOCK_NONBLOCK;
#else
int flags = 0;
#endif

int nfd = accept_socket(
pf->fd,SOCK_NONBLOCK,
pf->fd, flags,
client_ip, INET6_ADDRSTRLEN, client_port,NI_MAXSERV, client_host, NI_MAXHOST,
p->access_list, p->allow_dns
);

#ifndef SOCK_NONBLOCK
if (nfd > 0) {
int flags = fcntl(nfd, F_GETFL);
(void)fcntl(nfd, F_SETFL, flags| O_NONBLOCK);
}
#endif

if (unlikely(nfd < 0)) {
// accept failed

Expand Down
16 changes: 7 additions & 9 deletions src/libnetdata/socket/socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ bool sock_has_output_error(int fd);
int sock_setnonblock(int fd);
int sock_delnonblock(int fd);
int sock_setreuse(int fd, int reuse);
void sock_setcloexec(int fd);
int sock_setreuse_port(int fd, int reuse);
int sock_enlarge_in(int fd);
int sock_enlarge_out(int fd);
Expand All @@ -62,17 +63,14 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien

#ifndef HAVE_ACCEPT4
int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);

#ifndef SOCK_NONBLOCK
#define SOCK_NONBLOCK 00004000
#endif /* #ifndef SOCK_NONBLOCK */

#ifndef SOCK_CLOEXEC
#define SOCK_CLOEXEC 02000000
#endif /* #ifndef SOCK_CLOEXEC */

#endif /* #ifndef HAVE_ACCEPT4 */

#ifdef SOCK_CLOEXEC
#define DEFAULT_SOCKET_FLAGS SOCK_CLOEXEC
#else
#define DEFAULT_SOCKET_FLAGS 0
#endif


// ----------------------------------------------------------------------------
// poll() based listener
Expand Down
1 change: 1 addition & 0 deletions src/streaming/sender.c
Original file line number Diff line number Diff line change
Expand Up @@ -947,6 +947,7 @@ static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_p
nd_log(NDLS_DAEMON, NDLP_WARNING,
"STREAM %s [send to %s]: cannot set non-blocking mode for socket.",
rrdhost_hostname(host), s->connected_to);
sock_setcloexec(s->rrdpush_sender_socket);

if(sock_enlarge_out(s->rrdpush_sender_socket) < 0)
nd_log(NDLS_DAEMON, NDLP_WARNING,
Expand Down

0 comments on commit db63ab8

Please sign in to comment.