mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2025-11-20 06:59:44 -05:00
os: wrap recvmsg(MSG_CMSG_CLOEXEC)
Some system C libraries do not have MSG_CMSG_CLOEXEC. This flag would automatically set O_CLOEXEC flag on any received file descriptors. Provide a fallback that does it manually. If setting CLOEXEC fails, the file descriptor is closed immediately, which will lead to failures but avoid leaks. However, setting CLOEXEC is not really expected to fail occasionally. Add tests for the wrapper. The setup is copied from connection-test.c. Signed-off-by: Pekka Paalanen <ppaalanen@gmail.com>
This commit is contained in:
parent
2ccaf918ab
commit
35d5053c62
4 changed files with 229 additions and 1 deletions
|
|
@ -307,7 +307,7 @@ wl_connection_data(struct wl_connection *connection, uint32_t mask)
|
|||
msg.msg_flags = 0;
|
||||
|
||||
do {
|
||||
len = recvmsg(connection->fd, &msg, MSG_CMSG_CLOEXEC);
|
||||
len = wl_os_recvmsg_cloexec(connection->fd, &msg, 0);
|
||||
} while (len < 0 && errno == EINTR);
|
||||
|
||||
if (len < 0) {
|
||||
|
|
|
|||
|
|
@ -79,3 +79,48 @@ wl_os_dupfd_cloexec(int fd, long minfd)
|
|||
newfd = fcntl(fd, F_DUPFD, minfd);
|
||||
return set_cloexec_or_close(newfd);
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
recvmsg_cloexec_fallback(int sockfd, struct msghdr *msg, int flags)
|
||||
{
|
||||
ssize_t len;
|
||||
struct cmsghdr *cmsg;
|
||||
unsigned char *data;
|
||||
int *fd;
|
||||
int *end;
|
||||
|
||||
len = recvmsg(sockfd, msg, flags);
|
||||
if (len == -1)
|
||||
return -1;
|
||||
|
||||
if (!msg->msg_control || msg->msg_controllen == 0)
|
||||
return len;
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(msg);
|
||||
for (; cmsg != NULL; cmsg = CMSG_NXTHDR(msg, cmsg)) {
|
||||
if (cmsg->cmsg_level != SOL_SOCKET ||
|
||||
cmsg->cmsg_type != SCM_RIGHTS)
|
||||
continue;
|
||||
|
||||
data = CMSG_DATA(cmsg);
|
||||
end = (int *)(data + cmsg->cmsg_len - CMSG_LEN(0));
|
||||
for (fd = (int *)data; fd < end; ++fd)
|
||||
*fd = set_cloexec_or_close(*fd);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags)
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = recvmsg(sockfd, msg, flags | MSG_CMSG_CLOEXEC);
|
||||
if (len >= 0)
|
||||
return len;
|
||||
if (errno != EINVAL)
|
||||
return -1;
|
||||
|
||||
return recvmsg_cloexec_fallback(sockfd, msg, flags);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,10 @@ wl_os_socket_cloexec(int domain, int type, int protocol);
|
|||
int
|
||||
wl_os_dupfd_cloexec(int fd, long minfd);
|
||||
|
||||
ssize_t
|
||||
wl_os_recvmsg_cloexec(int sockfd, struct msghdr *msg, int flags);
|
||||
|
||||
|
||||
/*
|
||||
* The following are for wayland-os.c and the unit tests.
|
||||
* Do not use them elsewhere.
|
||||
|
|
@ -44,6 +48,10 @@ wl_os_dupfd_cloexec(int fd, long minfd);
|
|||
#define F_DUPFD_CLOEXEC 1030
|
||||
#endif
|
||||
|
||||
#ifndef MSG_CMSG_CLOEXEC
|
||||
#define MSG_CMSG_CLOEXEC 0x40000000
|
||||
#endif
|
||||
|
||||
#endif /* __linux__ */
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue