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. This improves things to give the nicer message: "Transport endpoint is not connected".
* lib/passfd.c (recvfd): Fake ENOTCONN if other end closes early. * tests/test-passfd.c (main): Enhance test to cover this. Signed-off-by: Eric Blake <ebl...@redhat.com> --- Jim suggested enhancing the testsuite, and it turned out to not be too difficult; so I'm pushing this now. ChangeLog | 6 ++++++ lib/passfd.c | 8 +++++--- tests/test-passfd.c | 8 ++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1753c8e..36ede18 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2013-12-24 Eric Blake <ebl...@redhat.com> + + passfd: give nicer error for recvfd at eof + * lib/passfd.c (recvfd): Fake ENOTCONN if other end closes early. + * tests/test-passfd.c (main): Enhance test to cover this. + 2013-12-17 Paul Eggert <egg...@cs.ucla.edu> gettimeofday: port recent C++ fix to Emacs diff --git a/lib/passfd.c b/lib/passfd.c index 44a9de7..5388ca5 100644 --- a/lib/passfd.c +++ b/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; } diff --git a/tests/test-passfd.c b/tests/test-passfd.c index 6389e15..3351233 100644 --- a/tests/test-passfd.c +++ b/tests/test-passfd.c @@ -83,6 +83,7 @@ main () /* father */ else { + ASSERT (close (pair[1]) == 0); fd = recvfd (pair[0], 0); if (fd == -1) { @@ -116,6 +117,13 @@ main () perror ("fstat"); return 80; } + + /* Check behavior when sender no longer around */ + errno = 0; + fd = recvfd (pair[0], 0); + ASSERT (fd == -1); + ASSERT (errno == ENOTCONN); + return 0; } #else -- 1.8.4.2