io: do not wait upon EINTR

When interrupted during a read/write syscall, do not wait before trying
again. Only wait if the error was EAGAIN which means that the other side
of the socket is not ready.

Signed-off-by: Robin Jarry <robin.jarry@6wind.com>
diff --git a/src/io.c b/src/io.c
index f7b9ec2..1effe50 100644
--- a/src/io.c
+++ b/src/io.c
@@ -75,7 +75,7 @@
 {
     size_t readd = 0;
     ssize_t r = -1;
-    int fd;
+    int fd, interrupted;
     struct timespec ts_cur, ts_inact_timeout;
 
     assert(session);
@@ -92,6 +92,7 @@
     nc_gettimespec_mono(&ts_inact_timeout);
     nc_addtimespec(&ts_inact_timeout, inact_timeout);
     do {
+        interrupted = 0;
         switch (session->ti_type) {
         case NC_TI_NONE:
             return 0;
@@ -102,9 +103,13 @@
             /* read via standard file descriptor */
             r = read(fd, buf + readd, count - readd);
             if (r < 0) {
-                if ((errno == EAGAIN) || (errno == EINTR)) {
+                if (errno == EAGAIN) {
                     r = 0;
                     break;
+                } else if (errno == EINTR) {
+                    r = 0;
+                    interrupted = 1;
+                    break;
                 } else {
                     ERR("Session %u: reading from file descriptor (%d) failed (%s).",
                         session->id, fd, strerror(errno));
@@ -190,7 +195,9 @@
 
         if (r == 0) {
             /* nothing read */
-            usleep(NC_TIMEOUT_STEP);
+            if (!interrupted) {
+                usleep(NC_TIMEOUT_STEP);
+            }
             nc_gettimespec_mono(&ts_cur);
             if ((nc_difftimespec(&ts_cur, &ts_inact_timeout) < 1) || (nc_difftimespec(&ts_cur, ts_act_timeout) < 1)) {
                 if (nc_difftimespec(&ts_cur, &ts_inact_timeout) < 1) {
@@ -700,7 +707,7 @@
 static int
 nc_write(struct nc_session *session, const void *buf, size_t count)
 {
-    int c, fd;
+    int c, fd, interrupted;
     size_t written = 0;
 #ifdef NC_ENABLED_TLS
     unsigned long e;
@@ -721,6 +728,7 @@
     DBG("Session %u: sending message:\n%.*s\n", session->id, count, buf);
 
     do {
+        interrupted = 0;
         switch (session->ti_type) {
         case NC_TI_FD:
         case NC_TI_UNIX:
@@ -728,6 +736,9 @@
             c = write(fd, (char *)(buf + written), count - written);
             if (c < 0 && errno == EAGAIN) {
                 c = 0;
+            } else if (c < 0 && errno == EINTR) {
+                c = 0;
+                interrupted = 1;
             } else if (c < 0) {
                 ERR("Session %u: socket error (%s).", session->id, strerror(errno));
                 return -1;
@@ -787,7 +798,7 @@
             return -1;
         }
 
-        if (c == 0) {
+        if (c == 0 && !interrupted) {
             /* we must wait */
             usleep(NC_TIMEOUT_STEP);
         }