Usually we need to set O_CLOEXEC, which is platform-specific. Add a wrapper like qemu_open() but for qemu_recvmsg(). Signed-off-by: Stefan Hajnoczi <stefanha@xxxxxxxxxxxxxxxxxx> --- block.c | 5 +---- osdep.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ qemu-common.h | 2 ++ 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/block.c b/block.c index d3bf443..e66d64f 100644 --- a/block.c +++ b/block.c @@ -176,10 +176,7 @@ int file_open(const char *filename, int flags, mode_t mode) msg.msg_control = &msg_control; msg.msg_controllen = sizeof(msg_control); - do { - ret = recvmsg(remote_file_fd, &msg, 0); - } while (ret == -1 && errno == EINTR); - if (ret != sizeof(OpenResponse)) { + if (qemu_recvmsg(remote_file_fd, &msg, 0) != sizeof(OpenResponse)) { errno = EPIPE; return -1; } diff --git a/osdep.c b/osdep.c index 3e6bada..834e78f 100644 --- a/osdep.c +++ b/osdep.c @@ -103,6 +103,52 @@ int qemu_open(const char *name, int flags, ...) } /* + * Receive a message from a socket + * + * This behaves like recvmsg(2) except that EINTR is handled internally and + * never returned. Passed file descriptors will have O_CLOEXEC set. + */ +ssize_t qemu_recvmsg(int fd, struct msghdr *msg, int flags) +{ + ssize_t ret; + +#ifdef MSG_CMSG_CLOEXEC + /* Receive file descriptors with O_CLOEXEC */ + flags |= MSG_CMSG_CLOEXEC; +#endif + + do { + ret = recvmsg(fd, msg, flags); + } while (ret == -1 && errno == EINTR); + if (ret < 0) { + return ret; + } + +#ifndef MSG_CMSG_CLOEXEC + /* As a fallback, set O_CLOEXEC in a way that is not thread-safe */ + { + struct cmsghdr *cmsg; + for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { + int new_fd; + + if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { + continue; + } + + new_fd = *((int *)CMSG_DATA(cmsg)); + if (new_fd >= 0) { + qemu_set_cloexec(new_fd); + } + } + } +#endif + + return ret; +} + +/* * A variant of write(2) which handles partial write. * * Return the number of bytes transferred. diff --git a/qemu-common.h b/qemu-common.h index 50f659a..e3a6c4d 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -184,6 +184,8 @@ const char *path(const char *pathname); void *qemu_oom_check(void *ptr); int qemu_open(const char *name, int flags, ...); +struct msghdr; +ssize_t qemu_recvmsg(int fd, struct msghdr *msg, int flags); ssize_t qemu_write_full(int fd, const void *buf, size_t count) QEMU_WARN_UNUSED_RESULT; ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags) -- 1.7.10 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list