Add non_block version of functions to UNIX socket wrapper
[lttng-tools.git] / src / common / unix.c
index e294936cade132a4771f9c65a8feb49cc5e26615..2f4df68e627bd37a0f6fc84fdfb868cc02de6bc1 100644 (file)
@@ -41,6 +41,14 @@ int lttcomm_connect_unix_sock(const char *pathname)
        struct sockaddr_un s_un;
        int fd, ret, closeret;
 
+       if (strlen(pathname) >= sizeof(s_un.sun_path)) {
+               ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
+                               pathname, strlen(pathname) + 1,
+                               sizeof(s_un.sun_path));
+               ret = -ENAMETOOLONG;
+               goto error;
+       }
+
        fd = socket(PF_UNIX, SOCK_STREAM, 0);
        if (fd < 0) {
                PERROR("socket");
@@ -82,7 +90,7 @@ int lttcomm_accept_unix_sock(int sock)
 {
        int new_fd;
        struct sockaddr_un s_un;
-       socklen_t len = 0;
+       socklen_t len = sizeof(s_un);
 
        /* Blocking call */
        new_fd = accept(sock, (struct sockaddr *) &s_un, &len);
@@ -111,9 +119,17 @@ LTTNG_HIDDEN
 int lttcomm_create_unix_sock(const char *pathname)
 {
        struct sockaddr_un s_un;
-       int fd;
+       int fd = -1;
        int ret = -1;
 
+       if (strlen(pathname) >= sizeof(s_un.sun_path)) {
+               ERR("unix socket address (\"%s\") is longer than the platform's limit (%zu > %zu).",
+                               pathname, strlen(pathname) + 1,
+                               sizeof(s_un.sun_path));
+               ret = -ENAMETOOLONG;
+               goto error;
+       }
+
        /* Create server socket */
        if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
                PERROR("socket");
@@ -200,6 +216,48 @@ ssize_t lttcomm_recv_unix_sock(int sock, void *buf, size_t len)
        return ret;
 }
 
+/*
+ * Receive data of size len in put that data into the buf param. Using recvmsg
+ * API. Only use with sockets set in non-blocking mode.
+ *
+ * Return the size of received data.
+ */
+LTTNG_HIDDEN
+ssize_t lttcomm_recv_unix_sock_non_block(int sock, void *buf, size_t len)
+{
+       struct msghdr msg;
+       struct iovec iov[1];
+       ssize_t ret;
+
+       memset(&msg, 0, sizeof(msg));
+
+       iov[0].iov_base = buf;
+       iov[0].iov_len = len;
+       msg.msg_iov = iov;
+       msg.msg_iovlen = 1;
+
+retry:
+       ret = lttng_recvmsg_nosigpipe(sock, &msg);
+       if (ret < 0) {
+               if (errno == EINTR) {
+                       goto retry;
+               } else {
+                       /*
+                        * Only warn about EPIPE when quiet mode is
+                        * deactivated.
+                        * We consider EPIPE as expected.
+                        */
+                       if (errno != EPIPE || !lttng_opt_quiet) {
+                               PERROR("recvmsg");
+                       }
+                       goto end;
+               }
+       }
+       ret = len;
+end:
+       return ret;
+}
+
 /*
  * Send buf data of size len. Using sendmsg API.
  *
@@ -210,7 +268,7 @@ ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len)
 {
        struct msghdr msg;
        struct iovec iov[1];
-       ssize_t ret = -1;
+       ssize_t ret;
 
        memset(&msg, 0, sizeof(msg));
 
@@ -219,17 +277,72 @@ ssize_t lttcomm_send_unix_sock(int sock, const void *buf, size_t len)
        msg.msg_iov = iov;
        msg.msg_iovlen = 1;
 
+       while (iov[0].iov_len) {
+               ret = sendmsg(sock, &msg, 0);
+               if (ret < 0) {
+                       if (errno == EINTR) {
+                               continue;
+                       } else {
+                               /*
+                                * Only warn about EPIPE when quiet mode is
+                                * deactivated.
+                                * We consider EPIPE as expected.
+                                */
+                               if (errno != EPIPE || !lttng_opt_quiet) {
+                                       PERROR("sendmsg");
+                               }
+                               goto end;
+                       }
+               }
+               iov[0].iov_len -= ret;
+               iov[0].iov_base += ret;
+       }
+       ret = len;
+end:
+       return ret;
+}
+
+/*
+ * Send buf data of size len. Using sendmsg API.
+ * Only use with non-blocking sockets. The difference with the blocking version
+ * of the function is that this one does not retry to send on partial sends,
+ * except if the interruption was caused by a signal (EINTR).
+ *
+ * Return the size of sent data.
+ */
+LTTNG_HIDDEN
+ssize_t lttcomm_send_unix_sock_non_block(int sock, const void *buf, size_t len)
+{
+       struct msghdr msg;
+       struct iovec iov[1];
+       ssize_t ret;
+
+       memset(&msg, 0, sizeof(msg));
+
+       iov[0].iov_base = (void *) buf;
+       iov[0].iov_len = len;
+       msg.msg_iov = iov;
+       msg.msg_iovlen = 1;
+
+retry:
        ret = sendmsg(sock, &msg, 0);
        if (ret < 0) {
-               /*
-                * Only warn about EPIPE when quiet mode is deactivated.
-                * We consider EPIPE as expected.
-                */
-               if (errno != EPIPE || !lttng_opt_quiet) {
-                       PERROR("sendmsg");
+               if (errno == EINTR) {
+                       goto retry;
+               } else {
+                       /*
+                        * Only warn about EPIPE when quiet mode is
+                        * deactivated.
+                        * We consider EPIPE as expected.
+                        */
+                       if (errno != EPIPE || !lttng_opt_quiet) {
+                               PERROR("sendmsg");
+                       }
+                       goto end;
                }
        }
-
+       ret = len;
+end:
        return ret;
 }
 
@@ -525,7 +638,7 @@ ssize_t lttcomm_recv_creds_unix_sock(int sock, void *buf, size_t len,
        }
 
        memcpy(creds, CMSG_DATA(cmptr), sizeof_cred);
-#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
+#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
        {
                int peer_ret;
 
@@ -558,7 +671,7 @@ int lttcomm_setsockopt_creds_unix_sock(int sock)
        }
        return ret;
 }
-#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__))
+#elif (defined(__FreeBSD__) || defined(__CYGWIN__) || defined(__sun__) || defined(__APPLE__))
 LTTNG_HIDDEN
 int lttcomm_setsockopt_creds_unix_sock(int sock)
 {
This page took 0.025353 seconds and 4 git commands to generate.