[tarantool-patches] [PATCH] Enable support for NOTIFY_SOCKET on macOS
Max Melentiev
dmarc-noreply at freelists.org
Mon Aug 19 11:28:13 MSK 2019
To make it possible to develop and test related features on macOS.
SOCK_CLOEXEC (not available on macOS) flag for socket()
is replaced with `fcntl(fd, F_SETFD, FD_CLOEXEC)` which has the same effect.
MSG_NOSIGNAL flag for sendmsg is also not available on macOS.
However it has SO_NOSIGPIPE flag for setsockopt which disables SIGPIPE.
So it requires different solution for different OS.
Inspired by https://nwat.xyz/blog/2014/01/16/porting-msg_more-and-msg_nosigpipe-to-osx/
`sendmsg()` is replaced with `sendto()` because `msg_namelen` was calculated incorrectly.
New method builds message automatically without errors.
---
src/systemd.c | 34 ++++++++++++++++++----------------
src/systemd.h | 25 ++++++++++++++++---------
src/trivia/config.h.cmake | 5 -----
3 files changed, 34 insertions(+), 30 deletions(-)
diff --git a/src/systemd.c b/src/systemd.c
index b6c48afe2..f49a7f3f9 100644
--- a/src/systemd.c
+++ b/src/systemd.c
@@ -30,7 +30,6 @@
*/
#include "systemd.h"
-#if defined(WITH_SYSTEMD)
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
@@ -68,11 +67,25 @@ int systemd_init() {
say_error("systemd: NOTIFY_SOCKET is longer that MAX_UNIX_PATH");
goto error;
}
- if ((systemd_fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0)) == -1) {
+ if ((systemd_fd = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1) {
say_syserror("systemd: failed to create unix socket");
goto error;
}
- int sndbuf_sz = 8 * 1024 * 1024;
+ if (fcntl(systemd_fd, F_SETFD, FD_CLOEXEC) == -1) {
+ say_syserror("systemd: fcntl failed to set FD_CLOEXEC");
+ goto error;
+ }
+
+ #ifdef SYSTEMD_USE_SO_NOSIGPIPE
+ int val = 1;
+ if (setsockopt(systemd_fd, SOL_SOCKET, SO_NOSIGPIPE, (void*)&val,
+ sizeof(val)) < 0) {
+ say_syserror("systemd: failed to set NOSIGPIPE");
+ goto error;
+ }
+ #endif
+
+ int sndbuf_sz = 4 * 1024 * 1024;
if (setsockopt(systemd_fd, SOL_SOCKET, SO_SNDBUF, &sndbuf_sz,
sizeof(int)) < 0) {
say_syserror("systemd: failed to set sndbuf size");
@@ -100,23 +113,13 @@ int systemd_notify(const char *message) {
struct sockaddr_un sa = {
.sun_family = AF_UNIX,
};
- struct iovec vec = {
- .iov_base = (char *)message,
- .iov_len = (size_t )strlen(message)
- };
- struct msghdr msg = {
- .msg_iov = &vec,
- .msg_iovlen = 1,
- .msg_name = &sa,
- };
-
- msg.msg_namelen = sizeof(sa.sun_family) + strlen(sd_unix_path);
strncpy(sa.sun_path, sd_unix_path, sizeof(sa.sun_path));
if (sa.sun_path[0] == '@')
sa.sun_path[0] = '\0';
say_debug("systemd: sending message '%s'", message);
- ssize_t sent = sendmsg(systemd_fd, &msg, MSG_NOSIGNAL);
+ ssize_t sent = sendto(systemd_fd, message, (size_t)strlen(message),
+ SYSTEMD_MSG_NOSIGNAL, (struct sockaddr*)&sa, sizeof(sa));
if (sent == -1) {
say_syserror("systemd: failed to send message");
return -1;
@@ -151,4 +154,3 @@ systemd_snotify(const char *format, ...)
va_end(args);
return res;
}
-#endif /* defined(WITH_SYSTEMD) */
diff --git a/src/systemd.h b/src/systemd.h
index f4f36e2cf..f86159581 100644
--- a/src/systemd.h
+++ b/src/systemd.h
@@ -35,11 +35,26 @@
#include "trivia/config.h"
+/*
+ * Linux supports MSG_NOSIGNAL flag for sendmsg.
+ * macOS lacks it, but has SO_NOSIGPIPE for setsockopt to achieve same behaviour.
+ */
+#ifdef MSG_NOSIGNAL
+# define SYSTEMD_MSG_NOSIGNAL MSG_NOSIGNAL
+#else
+# define SYSTEMD_MSG_NOSIGNAL 0
+# include <sys/socket.h>
+# ifdef SO_NOSIGPIPE
+# define SYSTEMD_USE_SO_NOSIGPIPE
+# else
+# error "No way to block SIGPIPE in sendmsg!"
+# endif
+#endif
+
#if defined(__cplusplus)
extern "C" {
#endif /* defined(__cplusplus) */
-#if defined(WITH_SYSTEMD)
/**
* Open connection with systemd daemon (using unix socket located in
* "NOTIFY_SOCKET" environmnent variable)
@@ -95,14 +110,6 @@ systemd_vsnotify(const char *format, va_list ap);
int
systemd_snotify(const char *format, ...);
-#else /* !defined(WITH_SYSTEMD) */
-# define systemd_init()
-# define systemd_free()
-# define systemd_notify(...)
-# define systemd_vsnotify(...)
-# define systemd_snotify(...)
-#endif /* WITH_SYSTEMD */
-
#if defined(__cplusplus)
} /* extern "C" */
#endif /* defined(__cplusplus) */
diff --git a/src/trivia/config.h.cmake b/src/trivia/config.h.cmake
index ca0057d2b..f50f64a02 100644
--- a/src/trivia/config.h.cmake
+++ b/src/trivia/config.h.cmake
@@ -201,11 +201,6 @@
*/
#cmakedefine HAVE_ICU_STRCOLLUTF8 1
-/*
-* Defined if systemd is enabled
- */
-#cmakedefine WITH_SYSTEMD 1
-
/** \cond public */
/** System configuration dir (e.g /etc) */
--
2.21.0
More information about the Tarantool-patches
mailing list