X-Git-Url: http://git.lttng.org/?a=blobdiff_plain;f=liblttng-ust-comm%2Flttng-ust-comm.c;h=3138016569e8d0c11d2036e2c2fb97225efc399a;hb=bf5ff35ed0a3a7f60e92d654a5b97e73b94da852;hp=2903d57574b68d3d11f839604a324fb81079bde2;hpb=4318ae1be57eb7983ab4857a7a8eeb4a030a8216;p=lttng-ust.git diff --git a/liblttng-ust-comm/lttng-ust-comm.c b/liblttng-ust-comm/lttng-ust-comm.c index 2903d575..31380165 100644 --- a/liblttng-ust-comm/lttng-ust-comm.c +++ b/liblttng-ust-comm/lttng-ust-comm.c @@ -1,19 +1,20 @@ /* * Copyright (C) 2011 - David Goulet + * Copyright (C) 2011 - Mathieu Desnoyers * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; only version 2 - * of the License. - * - * This program is distributed in the hope that it will be useful, + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; only + * version 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define _GNU_SOURCE @@ -28,8 +29,9 @@ #include #include #include +#include -#include +#include /* * Human readable error message. @@ -118,12 +120,17 @@ int ustcomm_connect_unix_sock(const char *pathname) * libust threads require the close-on-exec flag for all * resources so it does not leak file descriptors upon exec. */ - fd = socket(PF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + fd = socket(PF_UNIX, SOCK_STREAM, 0); if (fd < 0) { perror("socket"); ret = fd; goto error; } + ret = fcntl(fd, F_SETFD, FD_CLOEXEC); + if (ret < 0) { + perror("fcntl"); + goto error_fcntl; + } memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_UNIX; @@ -143,6 +150,7 @@ int ustcomm_connect_unix_sock(const char *pathname) return fd; error_connect: +error_fcntl: close(fd); error: return ret; @@ -236,17 +244,21 @@ int ustcomm_listen_unix_sock(int sock) */ ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len) { - struct msghdr msg = { 0 }; + struct msghdr msg; struct iovec iov[1]; ssize_t ret = -1; + memset(&msg, 0, sizeof(msg)); + iov[0].iov_base = buf; iov[0].iov_len = len; msg.msg_iov = iov; msg.msg_iovlen = 1; - ret = recvmsg(sock, &msg, 0); - if (ret < 0) { + do { + ret = recvmsg(sock, &msg, 0); + } while (ret < 0 && errno == EINTR); + if (ret < 0 && errno != EPIPE) { perror("recvmsg"); } @@ -261,10 +273,12 @@ ssize_t ustcomm_recv_unix_sock(int sock, void *buf, size_t len) */ ssize_t ustcomm_send_unix_sock(int sock, void *buf, size_t len) { - struct msghdr msg = { 0 }; + struct msghdr msg; struct iovec iov[1]; ssize_t ret = -1; + memset(&msg, 0, sizeof(msg)); + iov[0].iov_base = buf; iov[0].iov_len = len; msg.msg_iov = iov; @@ -277,8 +291,10 @@ ssize_t ustcomm_send_unix_sock(int sock, void *buf, size_t len) * by ignoring SIGPIPE, but we don't have this luxury on the * libust side. */ - ret = sendmsg(sock, &msg, MSG_NOSIGNAL); - if (ret < 0) { + do { + ret = sendmsg(sock, &msg, MSG_NOSIGNAL); + } while (ret < 0 && errno == EINTR); + if (ret < 0 && errno != EPIPE) { perror("sendmsg"); } @@ -294,10 +310,9 @@ int ustcomm_close_unix_sock(int sock) { int ret; - /* Shutdown receptions and transmissions */ - ret = shutdown(sock, SHUT_RDWR); + ret = close(sock); if (ret < 0) { - perror("shutdown"); + perror("close"); } return ret; @@ -310,13 +325,15 @@ int ustcomm_close_unix_sock(int sock) */ ssize_t ustcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, size_t len) { - struct msghdr msg = { 0 }; + struct msghdr msg; struct cmsghdr *cmptr; struct iovec iov[1]; ssize_t ret = -1; unsigned int sizeof_fds = nb_fd * sizeof(int); char tmp[CMSG_SPACE(sizeof_fds)]; + memset(&msg, 0, sizeof(msg)); + /* * Note: the consumerd receiver only supports receiving one FD per * message. @@ -339,8 +356,10 @@ ssize_t ustcomm_send_fds_unix_sock(int sock, void *buf, int *fds, size_t nb_fd, msg.msg_iov = iov; msg.msg_iovlen = 1; - ret = sendmsg(sock, &msg, 0); - if (ret < 0) { + do { + ret = sendmsg(sock, &msg, MSG_NOSIGNAL); + } while (ret < 0 && errno == EINTR); + if (ret < 0 && errno != EPIPE) { perror("sendmsg"); } @@ -354,16 +373,15 @@ int ustcomm_send_app_msg(int sock, struct ustcomm_ust_msg *lum) len = ustcomm_send_unix_sock(sock, lum, sizeof(*lum)); switch (len) { case sizeof(*lum): - printf("message successfully sent\n"); break; case -1: if (errno == ECONNRESET) { - printf("remote end closed connection\n"); + fprintf(stderr, "remote end closed connection\n"); return 0; } return -1; default: - printf("incorrect message size: %zd\n", len); + fprintf(stderr, "incorrect message size: %zd\n", len); return -1; } return 0; @@ -378,33 +396,35 @@ int ustcomm_recv_app_reply(int sock, struct ustcomm_ust_reply *lur, len = ustcomm_recv_unix_sock(sock, lur, sizeof(*lur)); switch (len) { case 0: /* orderly shutdown */ - printf("Application has performed an orderly shutdown\n"); return -EINVAL; case sizeof(*lur): - printf("result message received\n"); if (lur->handle != expected_handle) { - printf("Unexpected result message handle\n"); + fprintf(stderr, "Unexpected result message handle\n"); return -EINVAL; } if (lur->cmd != expected_cmd) { - printf("Unexpected result message command\n"); + fprintf(stderr, "Unexpected result message command\n"); return -EINVAL; } if (lur->ret_code != USTCOMM_OK) { - printf("remote operation failed with code %d.\n", - lur->ret_code); + /* + * Some errors are normal.. we should put this + * in a debug level message... + * fprintf(stderr, "remote operation failed with code %d.\n", + * lur->ret_code); + */ return lur->ret_code; } return 0; case -1: if (errno == ECONNRESET) { - printf("remote end closed connection\n"); + fprintf(stderr, "remote end closed connection\n"); return -EINVAL; } return -1; default: - printf("incorrect message size: %zd\n", len); + fprintf(stderr, "incorrect message size: %zd\n", len); return len > 0 ? -1 : len; } } @@ -437,13 +457,15 @@ int ustcomm_recv_fd(int sock) int data_fd; struct cmsghdr *cmsg; char recv_fd[CMSG_SPACE(sizeof(int))]; - struct msghdr msg = { 0 }; + struct msghdr msg; union { unsigned char vc[4]; int vi; } tmp; int i; + memset(&msg, 0, sizeof(msg)); + /* Prepare to receive the structures */ iov[0].iov_base = &data_fd; iov[0].iov_len = sizeof(data_fd); @@ -452,23 +474,27 @@ int ustcomm_recv_fd(int sock) msg.msg_control = recv_fd; msg.msg_controllen = sizeof(recv_fd); - printf("Waiting to receive fd\n"); - if ((ret = recvmsg(sock, &msg, 0)) < 0) { - perror("recvmsg"); + do { + ret = recvmsg(sock, &msg, 0); + } while (ret < 0 && errno == EINTR); + if (ret < 0) { + if (errno != EPIPE) { + perror("recvmsg"); + } goto end; } if (ret != sizeof(data_fd)) { - printf("Received %d bytes, expected %ld", ret, sizeof(data_fd)); + fprintf(stderr, "Received %d bytes, expected %zd", ret, sizeof(data_fd)); goto end; } cmsg = CMSG_FIRSTHDR(&msg); if (!cmsg) { - printf("Invalid control message header\n"); + fprintf(stderr, "Invalid control message header\n"); ret = -1; goto end; } if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) { - printf("Didn't received any fd\n"); + fprintf(stderr, "Didn't received any fd\n"); ret = -1; goto end; } @@ -476,7 +502,92 @@ int ustcomm_recv_fd(int sock) for (i = 0; i < sizeof(int); i++) tmp.vc[i] = CMSG_DATA(cmsg)[i]; ret = tmp.vi; - printf("received fd %d\n", ret); + /* + * Useful for fd leak debug. + * fprintf(stderr, "received fd %d\n", ret); + */ +end: + return ret; +} + +ssize_t ustcomm_send_string(int sock, char *str, size_t len) +{ + ssize_t slen, ret = -1; + + if (!str) { + goto end; + } + + /* Send string len first */ + slen = ustcomm_send_unix_sock(sock, &len, sizeof(len)); + + if (slen != sizeof(len)) { + fprintf(stderr, + "Unexpected sent size. Expected %zu got %zu\n", + sizeof(len), slen); + ret = -1; + goto end; + } + + /* Send the actual string */ + slen = ustcomm_send_unix_sock(sock, str, len); + if (slen != len) { + fprintf(stderr, + "Unexpected sent size. Expected %zu got %zu\n", + len, slen); + ret = -1; + goto end; + } + + ret = slen; + +end: + return ret; +} + +/* + * Allocate and return the received string. + * Return NULL on error. + * Caller is responsible of freeing the allocated string. + */ +char *ustcomm_recv_string(int sock) +{ + ssize_t rlen; + size_t len; + char *ret; + + /* Get the string len first */ + rlen = ustcomm_recv_unix_sock(sock, &len, sizeof(len)); + + if (rlen != sizeof(len)) { + fprintf(stderr, + "Unexpected received size. Expected %zu got %zu\n", + sizeof(len), rlen); + ret = NULL; + goto end; + } + + /* Account for the NULL byte */ + ret = malloc(len + 1); + if (!ret) { + ret = NULL; + goto end; + } + + /* Get the actual string */ + rlen = ustcomm_recv_unix_sock(sock, ret, len); + if (rlen != len) { + fprintf(stderr, + "Unexpected received size. Expected %zu got %zu\n", + len, rlen); + free(ret); + ret = NULL; + goto end; + } + + /* Set terminating NULL byte */ + ret[len] = '\0'; + end: return ret; }