Add android/utils/eintr_wrapper.h

Add a new Android-specific header that defines two macros to
handle EINTR in a consistent way, as well as allow detecting
when a system call loops too many times and exit with a fatal
error message when that happens.

+ Unit tests.

+ Update existing code under android/ which uses to deal directly
  with EINTR to use the new HANDLE_EINTR() and IGNORE_EINTR()

+ Remove EINTR checks for functions that call socket_xxx() functions
  which already loop around EINTR.

Change-Id: I1d2ee64d9743a2edc506f616465ea091878db620
diff --git a/android/protocol/fb-updates-impl.c b/android/protocol/fb-updates-impl.c
index dde79c1..e36c4bf 100644
--- a/android/protocol/fb-updates-impl.c
+++ b/android/protocol/fb-updates-impl.c
@@ -17,6 +17,7 @@
 
 #include "android/utils/system.h"
 #include "android/utils/debug.h"
+#include "android/utils/eintr_wrapper.h"
 #include "android/utils/panic.h"
 #include "android/sync-utils.h"
 #include "android/protocol/core-connection.h"
@@ -113,21 +114,20 @@
     // Read updates while they are immediately available.
     for (;;) {
         // Read next chunk of data.
-        ret = socket_recv(fbi->sock, fbi->reader_buffer + fbi->reader_offset,
-                          fbi->reader_bytes - fbi->reader_offset);
-        if (ret == 0) {
-            /* disconnection ! */
-            fbUpdatesImpl_destroy();
+        ret = HANDLE_EINTR(
+                socket_recv(fbi->sock,
+                            fbi->reader_buffer + fbi->reader_offset,
+                            fbi->reader_bytes - fbi->reader_offset));
+        if (ret < 0 && (errno == EWOULDBLOCK || errno == EAGAIN)) {
+            // Chunk is not avalable at this point. Come back later.
             return;
         }
-        if (ret < 0) {
-            if (errno == EINTR) {
-                /* loop on EINTR */
-                continue;
-            } else if (errno == EWOULDBLOCK || errno == EAGAIN) {
-                // Chunk is not avalable at this point. Come back later.
-                return;
-            }
+        if (ret <= 0) {
+            /* disconnection ! */
+            derror("Unable to receive framebuffer data: %s\n",
+                   ret < 0 ? strerror(errno), "unexpected disconnection");
+            fbUpdatesImpl_destroy();
+            return;
         }
 
         fbi->reader_offset += ret;