X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Funix.c;h=2f4df68e627bd37a0f6fc84fdfb868cc02de6bc1;hp=e294936cade132a4771f9c65a8feb49cc5e26615;hb=c72435ad89dc397f89a30faea35274074fbb3047;hpb=2038dd6ce78bc856ece474626b7f039d19860bce diff --git a/src/common/unix.c b/src/common/unix.c index e294936ca..2f4df68e6 100644 --- a/src/common/unix.c +++ b/src/common/unix.c @@ -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) {