[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
possible recvfd() improvement
From: |
Eric Blake |
Subject: |
possible recvfd() improvement |
Date: |
Sat, 21 Dec 2013 00:27:46 -0700 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.2.0 |
I noticed that recvfd() fails with errno set to EACCES if the other end
of the socket has closed (such as if it calls _exit()); but "Permission
denied" as the strerror() message doesn't read very well. Any
objections to a patch along these lines to give a nicer error message
"Transport endpoint is not connected"? Or any better errno value to
use? ECONNABORTED? ENOLINK?
diff --git i/ChangeLog w/ChangeLog
index 25b59e3..f608556 100644
--- i/ChangeLog
+++ w/ChangeLog
@@ -1,3 +1,8 @@
+2013-12-21 Eric Blake <address@hidden>
+
+ passfd: give nicer error for recvfd at eof
+ * lib/passfd.c (recvfd): Fake ENOTCONN if other end closes early.
+
2013-12-04 Eric Blake <address@hidden>
absolute-header: port to IBM Blue Gene compilers
diff --git i/lib/passfd.c w/lib/passfd.c
index 44a9de7..5388ca5 100644
--- i/lib/passfd.c
+++ w/lib/passfd.c
@@ -110,6 +110,7 @@ recvfd (int sock, int flags)
struct iovec iov;
struct msghdr msg;
int fd = -1;
+ ssize_t len;
# ifdef CMSG_FIRSTHDR
struct cmsghdr *cmsg;
char buf[CMSG_SPACE (sizeof fd)];
@@ -142,16 +143,17 @@ recvfd (int sock, int flags)
memcpy (CMSG_DATA (cmsg), &fd, sizeof fd);
msg.msg_controllen = cmsg->cmsg_len;
- if (recvmsg (sock, &msg, flags_recvmsg) < 0)
+ len = recvmsg (sock, &msg, flags_recvmsg);
+ if (len < 0)
return -1;
cmsg = CMSG_FIRSTHDR (&msg);
/* be paranoiac */
- if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd)
+ if (len == 0 || cmsg == NULL || cmsg->cmsg_len != CMSG_LEN (sizeof fd)
|| cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
{
/* fake errno: at end the file is not available */
- errno = EACCES;
+ errno = len ? EACCES : ENOTCONN;
return -1;
}
Here's the crude program I tested with:
$ cat foo.c
#include <config.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include "passfd.h"
int main(void) {
int fds[2];
pid_t pid;
int fd;
int status;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0)
exit(1);
pid = fork();
if (pid < 0)
exit(2);
if (pid == 0) {
sleep(3);
_exit(127);
}
close(fds[1]);
fd = recvfd(fds[0], 0);
if (fd < 0) {
perror("hi");
exit(3);
}
if (waitpid(pid, &status, 0) != pid)
exit(4);
if (status)
exit(5);
exit(0);
}
$ gcc -o foo -Wall -I. -Ignulib/lib foo.c -g gnulib/lib/.libs/libgnu.a
for a project that was using the passlib module from gnulib.
--
Eric Blake eblake redhat com +1-919-301-3266
Libvirt virtualization library http://libvirt.org
signature.asc
Description: OpenPGP digital signature
- possible recvfd() improvement,
Eric Blake <=