Fix macOS issue with SOCK_CLOEXEC (#17151)
* Fix macos issue with SOCK_CLOEXEC * Code cleanup * Fix SOCK_NONBLOCK not available * Fix compilation error * Code simplify * Properly check return code
Stelios Fragkakis committed
Mar 15, 2024 at 15:28 UTC
db63ab82265f0606e33600a350e4ee6cc2dda687
5 files changed
+55
-25
src/aclk/mqtt_websockets/mqtt_wss_client.c
+7
-1
@@ -583,12 +583,18 @@ int mqtt_wss_connect(mqtt_wss_client client, char *host, int port, struct mqtt_c
583
584
if (client->sockfd > 0)
585
close(client->sockfd);
586
- client->sockfd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
586
+ client->sockfd = socket(AF_INET, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
587
if (client->sockfd < 0) {
588
mws_error(client->log, "Couldn't create socket()");
589
return -1;
590
}
591
592
+#ifndef SOCK_CLOEXEC
593
+ int flags = fcntl(client->sockfd, F_GETFD);
594
+ if (flags != -1)
595
+ (void) fcntl(client->sockfd, F_SETFD, flags| FD_CLOEXEC);
596
+#endif
597
+
598
int flag = 1;
599
int result = setsockopt(client->sockfd,
600
IPPROTO_TCP,
src/libnetdata/log/journal.c
+3
-1
@@ -48,9 +48,11 @@ int journal_direct_fd(const char *path) {
48
if(!is_path_unix_socket(path))
49
return -1;
50
51
- int fd = socket(AF_UNIX, SOCK_DGRAM| SOCK_CLOEXEC, 0);
51
+ int fd = socket(AF_UNIX, SOCK_DGRAM| DEFAULT_SOCKET_FLAGS, 0);
52
if (fd < 0) return -1;
53
54
+ sock_setcloexec(fd);
55
+
56
struct sockaddr_un addr;
57
memset(&addr, 0, sizeof(struct sockaddr_un));
58
addr.sun_family = AF_UNIX;
src/libnetdata/socket/socket.c
+37
-14
@@ -191,6 +191,16 @@ int sock_setreuse(int fd, int reuse) {
191
return ret;
192
}
193
194
+void sock_setcloexec(int fd)
195
+{
196
+ UNUSED(fd);
197
+#ifndef SOCK_CLOEXEC
198
+ int flags = fcntl(fd, F_GETFD);
199
+ if (flags != -1)
200
+ (void) fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
201
+#endif
202
+}
203
+
204
int sock_setreuse_port(int fd, int reuse) {
205
int ret;
206
@@ -262,7 +272,7 @@ char *strdup_client_description(int family, const char *protocol, const char *ip
272
int create_listen_socket_unix(const char *path, int listen_backlog) {
273
int sock;
274
265
- sock = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
275
+ sock = socket(AF_UNIX, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
276
if(sock < 0) {
277
nd_log(NDLS_DAEMON, NDLP_ERR,
278
"LISTENER: UNIX socket() on path '%s' failed.",
@@ -272,6 +282,7 @@ int create_listen_socket_unix(const char *path, int listen_backlog) {
282
}
283
284
sock_setnonblock(sock);
285
+ sock_setcloexec(sock);
286
sock_enlarge_in(sock);
287
288
struct sockaddr_un name;
@@ -316,7 +327,7 @@ int create_listen_socket_unix(const char *path, int listen_backlog) {
327
int create_listen_socket4(int socktype, const char *ip, uint16_t port, int listen_backlog) {
328
int sock;
329
319
- sock = socket(AF_INET, socktype | SOCK_CLOEXEC, 0);
330
+ sock = socket(AF_INET, socktype | DEFAULT_SOCKET_FLAGS, 0);
331
if(sock < 0) {
332
nd_log(NDLS_DAEMON, NDLP_ERR,
333
"LISTENER: IPv4 socket() on ip '%s' port %d, socktype %d failed.",
@@ -324,10 +335,10 @@ int create_listen_socket4(int socktype, const char *ip, uint16_t port, int liste
335
336
return -1;
337
}
327
-
338
sock_setreuse(sock, 1);
339
sock_setreuse_port(sock, 0);
340
sock_setnonblock(sock);
341
+ sock_setcloexec(sock);
342
sock_enlarge_in(sock);
343
344
struct sockaddr_in name;
@@ -374,7 +385,7 @@ int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int p
385
int sock;
386
int ipv6only = 1;
387
377
- sock = socket(AF_INET6, socktype | SOCK_CLOEXEC, 0);
388
+ sock = socket(AF_INET6, socktype | DEFAULT_SOCKET_FLAGS, 0);
389
if (sock < 0) {
390
nd_log(NDLS_DAEMON, NDLP_ERR,
391
"LISTENER: IPv6 socket() on ip '%s' port %d, socktype %d, failed.",
@@ -382,10 +393,10 @@ int create_listen_socket6(int socktype, uint32_t scope_id, const char *ip, int p
393
394
return -1;
395
}
385
-
396
sock_setreuse(sock, 1);
397
sock_setreuse_port(sock, 0);
398
sock_setnonblock(sock);
399
+ sock_setcloexec(sock);
400
sock_enlarge_in(sock);
401
402
/* IPv6 only */
@@ -781,7 +792,7 @@ int listen_sockets_setup(LISTEN_SOCKETS *sockets) {
792
// timeout the timeout for establishing a connection
793
794
static inline int connect_to_unix(const char *path, struct timeval *timeout) {
784
- int fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
795
+ int fd = socket(AF_UNIX, SOCK_STREAM | DEFAULT_SOCKET_FLAGS, 0);
796
if(fd == -1) {
797
nd_log(NDLS_DAEMON, NDLP_ERR,
798
"Failed to create UNIX socket() for '%s'",
@@ -797,6 +808,8 @@ static inline int connect_to_unix(const char *path, struct timeval *timeout) {
808
path);
809
}
810
811
+ sock_setcloexec(fd);
812
+
813
struct sockaddr_un addr;
814
memset(&addr, 0, sizeof(addr));
815
addr.sun_family = AF_UNIX;
@@ -894,7 +907,7 @@ int connect_to_this_ip46(int protocol, int socktype, const char *host, uint32_t
907
}
908
}
909
897
- fd = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, ai->ai_protocol);
910
+ fd = socket(ai->ai_family, ai->ai_socktype | DEFAULT_SOCKET_FLAGS, ai->ai_protocol);
911
if(fd != -1) {
912
if(timeout) {
913
if(setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *) timeout, sizeof(struct timeval)) < 0)
@@ -902,6 +915,7 @@ int connect_to_this_ip46(int protocol, int socktype, const char *host, uint32_t
915
"Failed to set timeout on the socket to ip '%s' port '%s'",
916
hostBfr, servBfr);
917
}
918
+ sock_setcloexec(fd);
919
920
errno = 0;
921
if(connect(fd, ai->ai_addr, ai->ai_addrlen) < 0) {
@@ -1266,11 +1280,6 @@ int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags) {
1280
1281
if (fd < 0) return fd;
1282
1269
- if (flags & SOCK_NONBLOCK) {
1270
- newflags |= O_NONBLOCK;
1271
- flags &= ~SOCK_NONBLOCK;
1272
- }
1273
-
1283
#ifdef SOCK_CLOEXEC
1284
#ifdef O_CLOEXEC
1285
if (flags & SOCK_CLOEXEC) {
@@ -1387,7 +1396,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
1396
struct sockaddr_storage sadr;
1397
socklen_t addrlen = sizeof(sadr);
1398
1390
- int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags | SOCK_CLOEXEC);
1399
+ int nfd = accept4(fd, (struct sockaddr *)&sadr, &addrlen, flags | DEFAULT_SOCKET_FLAGS);
1400
if (likely(nfd >= 0)) {
1401
if (getnameinfo((struct sockaddr *)&sadr, addrlen, client_ip, (socklen_t)ipsize,
1402
client_port, (socklen_t)portsize, NI_NUMERICHOST | NI_NUMERICSERV) != 0) {
@@ -1401,6 +1410,7 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
1410
if (!strcmp(client_ip, "127.0.0.1") || !strcmp(client_ip, "::1")) {
1411
strncpyz(client_ip, "localhost", ipsize);
1412
}
1413
+ sock_setcloexec(nfd);
1414
1415
#ifdef __FreeBSD__
1416
if(((struct sockaddr *)&sadr)->sa_family == AF_LOCAL)
@@ -1785,12 +1795,25 @@ static int poll_process_new_tcp_connection(POLLJOB *p, POLLINFO *pi, struct poll
1795
char client_port[NI_MAXSERV] = "";
1796
char client_host[NI_MAXHOST] = "";
1797
1798
+#ifdef SOCK_NONBLOCK
1799
+ int flags = SOCK_NONBLOCK;
1800
+#else
1801
+ int flags = 0;
1802
+#endif
1803
+
1804
int nfd = accept_socket(
1789
- pf->fd,SOCK_NONBLOCK,
1805
+ pf->fd, flags,
1806
client_ip, INET6_ADDRSTRLEN, client_port,NI_MAXSERV, client_host, NI_MAXHOST,
1807
p->access_list, p->allow_dns
1808
);
1809
1810
+#ifndef SOCK_NONBLOCK
1811
+ if (nfd > 0) {
1812
+ int flags = fcntl(nfd, F_GETFL);
1813
+ (void)fcntl(nfd, F_SETFL, flags| O_NONBLOCK);
1814
+ }
1815
+#endif
1816
+
1817
if (unlikely(nfd < 0)) {
1818
// accept failed
1819
src/libnetdata/socket/socket.h
+7
-9
@@ -51,6 +51,7 @@ bool sock_has_output_error(int fd);
51
int sock_setnonblock(int fd);
52
int sock_delnonblock(int fd);
53
int sock_setreuse(int fd, int reuse);
54
+void sock_setcloexec(int fd);
55
int sock_setreuse_port(int fd, int reuse);
56
int sock_enlarge_in(int fd);
57
int sock_enlarge_out(int fd);
@@ -62,17 +63,14 @@ int accept_socket(int fd, int flags, char *client_ip, size_t ipsize, char *clien
63
64
#ifndef HAVE_ACCEPT4
65
int accept4(int sock, struct sockaddr *addr, socklen_t *addrlen, int flags);
65
-
66
-#ifndef SOCK_NONBLOCK
67
-#define SOCK_NONBLOCK 00004000
68
-#endif /* #ifndef SOCK_NONBLOCK */
69
-
70
-#ifndef SOCK_CLOEXEC
71
-#define SOCK_CLOEXEC 02000000
72
-#endif /* #ifndef SOCK_CLOEXEC */
73
-
66
#endif /* #ifndef HAVE_ACCEPT4 */
67
68
+#ifdef SOCK_CLOEXEC
69
+#define DEFAULT_SOCKET_FLAGS SOCK_CLOEXEC
70
+#else
71
+#define DEFAULT_SOCKET_FLAGS 0
72
+#endif
73
+
74
75
// ----------------------------------------------------------------------------
76
// poll() based listener
src/streaming/sender.c
+1
@@ -947,6 +947,7 @@ static bool rrdpush_sender_thread_connect_to_parent(RRDHOST *host, int default_p
947
nd_log(NDLS_DAEMON, NDLP_WARNING,
948
"STREAM %s [send to %s]: cannot set non-blocking mode for socket.",
949
rrdhost_hostname(host), s->connected_to);
950
+ sock_setcloexec(s->rrdpush_sender_socket);
951
952
if(sock_enlarge_out(s->rrdpush_sender_socket) < 0)
953
nd_log(NDLS_DAEMON, NDLP_WARNING,