io BUGFIX do not fail when there is data left to read (#229)

When using the UNIX transport and depending on the timing between the
server and client, the client may read the final reply to the
<close-session> rpc *after* the server has closed the socket. When that
occurs, poll() returns POLLHUP in revents meaning the server closed the
socket which causes the following error on the client:

  ERR: Session 1: communication channel unexpectedly closed.
  ERR: Session 1: failed to receive a reply to <close-session>.

When POLLHUP is returned in revents, make sure POLLIN is not present as
well (if it is, it means that there is some data left to be read in the
socket buffer).

Link: https://www.greenend.org.uk/rjk/tech/poll.html
Signed-off-by: Robin Jarry <robin.jarry@6wind.com>
diff --git a/src/io.c b/src/io.c
index e469bd3..e55add8 100644
--- a/src/io.c
+++ b/src/io.c
@@ -605,18 +605,20 @@
         return -1;
     } else { /* status > 0 */
         /* in case of standard (non-libssh) poll, there still can be an error */
-        if (fds.revents & POLLHUP) {
-            ERR("Session %u: communication channel unexpectedly closed.", session->id);
-            session->status = NC_STATUS_INVALID;
-            session->term_reason = NC_SESSION_TERM_DROPPED;
-            return -1;
-        }
         if (fds.revents & POLLERR) {
             ERR("Session %u: communication channel error.", session->id);
             session->status = NC_STATUS_INVALID;
             session->term_reason = NC_SESSION_TERM_OTHER;
             return -1;
         }
+        /* Some poll() implementations may return POLLHUP|POLLIN when the other
+         * side has closed but there is data left to read in the buffer. */
+        if ((fds.revents & POLLHUP) && !(fds.revents & POLLIN)) {
+            ERR("Session %u: communication channel unexpectedly closed.", session->id);
+            session->status = NC_STATUS_INVALID;
+            session->term_reason = NC_SESSION_TERM_DROPPED;
+            return -1;
+        }
     }
 
     return ret;