passfd: give nicer error for recvfd at eof
authorEric Blake <eblake@redhat.com>
Tue, 24 Dec 2013 18:16:07 +0000 (11:16 -0700)
committerEric Blake <eblake@redhat.com>
Tue, 24 Dec 2013 18:21:44 +0000 (11:21 -0700)
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>
ChangeLog
lib/passfd.c
tests/test-passfd.c

index 1753c8e..36ede18 100644 (file)
--- 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
 2013-12-17  Paul Eggert  <eggert@cs.ucla.edu>
 
        gettimeofday: port recent C++ fix to Emacs
index 44a9de7..5388ca5 100644 (file)
@@ -110,6 +110,7 @@ recvfd (int sock, int flags)
   struct iovec iov;
   struct msghdr msg;
   int fd = -1;
   struct iovec iov;
   struct msghdr msg;
   int fd = -1;
+  ssize_t len;
 # ifdef CMSG_FIRSTHDR
   struct cmsghdr *cmsg;
   char buf[CMSG_SPACE (sizeof fd)];
 # 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;
 
   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 */
     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 */
       || 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;
     }
 
       return -1;
     }
 
index 6389e15..3351233 100644 (file)
@@ -83,6 +83,7 @@ main ()
   /* father */
   else
     {
   /* father */
   else
     {
+      ASSERT (close (pair[1]) == 0);
       fd = recvfd (pair[0], 0);
       if (fd == -1)
         {
       fd = recvfd (pair[0], 0);
       if (fd == -1)
         {
@@ -116,6 +117,13 @@ main ()
           perror ("fstat");
           return 80;
         }
           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
       return 0;
     }
 #else