changeset 17584:c67bafa8ca26

passfd: give nicer error for recvfd at eof 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 <eblake@redhat.com>
author Eric Blake <eblake@redhat.com>
date Tue, 24 Dec 2013 11:16:07 -0700
parents 4c8a98f49e21
children bf17232de8ba
files ChangeLog lib/passfd.c tests/test-passfd.c
diffstat 3 files changed, 19 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-12-24  Eric Blake  <eblake@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  <eggert@cs.ucla.edu>
 
 	gettimeofday: port recent C++ fix to Emacs
--- a/lib/passfd.c
+++ b/lib/passfd.c
@@ -110,6 +110,7 @@
   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 @@
   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;
     }
 
--- a/tests/test-passfd.c
+++ b/tests/test-passfd.c
@@ -83,6 +83,7 @@
   /* father */
   else
     {
+      ASSERT (close (pair[1]) == 0);
       fd = recvfd (pair[0], 0);
       if (fd == -1)
         {
@@ -116,6 +117,13 @@
           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