Restart failed system calls interrupted with errno of EINTR

In number of places we don't handle properly system calls failures
when the errno is EINTR (i.e., the system call was interrupted
by a signal). In all our use cases, the system calls should be
restarted. The handling of the following system calls (as used in the code)
has been updated/fixed:

  poll, send, recv, sendmsg, nanosleep, epoll_wait
  read - mostly (e.g., socket-like fds)
  write - mostly (e.g., socket-like fds)
  select, accept, connect

Bug: 28471477
Bug: 28658141
Change-Id: I03e6f0f67e33876780fb6d02c33eb84547ba8f95
diff --git a/audio_a2dp_hw/audio_a2dp_hw.c b/audio_a2dp_hw/audio_a2dp_hw.c
index df2b92b..bbd7f95 100644
--- a/audio_a2dp_hw/audio_a2dp_hw.c
+++ b/audio_a2dp_hw/audio_a2dp_hw.c
@@ -47,6 +47,7 @@
 #include "osi/include/hash_map.h"
 #include "osi/include/hash_map_utils.h"
 #include "osi/include/log.h"
+#include "osi/include/osi.h"
 #include "osi/include/socket_utils/sockets.h"
 
 /*****************************************************************************
@@ -247,36 +248,31 @@
 
 static int skt_read(int fd, void *p, size_t len)
 {
-    int read;
+    ssize_t read;
 
     FNLOG();
 
     ts_log("skt_read recv", len, NULL);
 
-    if ((read = recv(fd, p, len, MSG_NOSIGNAL)) == -1)
-    {
+    OSI_NO_INTR(read = recv(fd, p, len, MSG_NOSIGNAL));
+    if (read == -1)
         ERROR("read failed with errno=%d\n", errno);
-        return -1;
-    }
 
-    return read;
+    return (int)read;
 }
 
 static int skt_write(int fd, const void *p, size_t len)
 {
-    int sent;
+    ssize_t sent;
 
     FNLOG();
 
     ts_log("skt_write", len, NULL);
-
-    if ((sent = send(fd, p, len, MSG_NOSIGNAL)) == -1)
-    {
+    OSI_NO_INTR(sent = send(fd, p, len, MSG_NOSIGNAL));
+    if (sent == -1)
         ERROR("write failed with errno=%d\n", errno);
-        return -1;
-    }
 
-    return sent;
+    return (int)sent;
 }
 
 static int skt_disconnect(int fd)
@@ -301,29 +297,15 @@
 
 static int a2dp_ctrl_receive(struct a2dp_stream_common *common, void* buffer, int length)
 {
-    int ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL);
+    ssize_t ret;
+
+    OSI_NO_INTR(ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL));
     if (ret < 0)
     {
         ERROR("ack failed (%s)", strerror(errno));
-        if (errno == EINTR)
-        {
-            /* retry again */
-            ret = recv(common->ctrl_fd, buffer, length, MSG_NOSIGNAL);
-            if (ret < 0)
-            {
-               ERROR("ack failed (%s)", strerror(errno));
-               skt_disconnect(common->ctrl_fd);
-               common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
-               return -1;
-            }
-        }
-        else
-        {
-               skt_disconnect(common->ctrl_fd);
-               common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
-               return -1;
-
-        }
+        skt_disconnect(common->ctrl_fd);
+        common->ctrl_fd = AUDIO_SKT_DISCONNECTED;
+        return -1;
     }
     return ret;
 }
@@ -335,7 +317,9 @@
     DEBUG("A2DP COMMAND %s", dump_a2dp_ctrl_event(cmd));
 
     /* send command */
-    if (send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL) == -1)
+    ssize_t sent;
+    OSI_NO_INTR(sent = send(common->ctrl_fd, &cmd, 1, MSG_NOSIGNAL));
+    if (sent == -1)
     {
         ERROR("cmd failed (%s)", strerror(errno));
         skt_disconnect(common->ctrl_fd);
diff --git a/btif/co/bta_hh_co.cc b/btif/co/bta_hh_co.cc
index cbb0507..be5d5d8 100644
--- a/btif/co/bta_hh_co.cc
+++ b/btif/co/bta_hh_co.cc
@@ -29,6 +29,7 @@
 #include <unistd.h>
 #include <linux/uhid.h>
 #include <unistd.h>
+#include "osi/include/osi.h"
 #include "btif_hh.h"
 #include "bta_api.h"
 #include "bta_hh_api.h"
@@ -58,8 +59,9 @@
 /*Internal function to perform UHID write and error checking*/
 static int uhid_write(int fd, const struct uhid_event *ev)
 {
-    ssize_t ret = write(fd, ev, sizeof(*ev));
+    ssize_t ret;
 
+    OSI_NO_INTR(ret = write(fd, ev, sizeof(*ev)));
     if (ret < 0){
         int rtn = -errno;
         APPL_TRACE_ERROR("%s: Cannot write to uhid:%s",
@@ -198,7 +200,6 @@
     btif_hh_device_t *p_dev = (btif_hh_device_t*)arg;
     APPL_TRACE_DEBUG("%s: Thread created fd = %d", __func__, p_dev->fd);
     struct pollfd pfds[1];
-    int ret;
 
     pfds[0].fd = p_dev->fd;
     pfds[0].events = POLLIN;
@@ -207,7 +208,8 @@
     uhid_set_non_blocking(p_dev->fd);
 
     while(p_dev->hh_keep_polling){
-        ret = poll(pfds, 1, 50);
+        int ret;
+        OSI_NO_INTR(ret = poll(pfds, 1, 50));
         if (ret < 0) {
             APPL_TRACE_ERROR("%s: Cannot poll for fds: %s\n", __func__, strerror(errno));
             break;
diff --git a/btif/co/bta_hl_co.cc b/btif/co/bta_hl_co.cc
index 31cd72f..e76d078 100644
--- a/btif/co/bta_hl_co.cc
+++ b/btif/co/bta_hl_co.cc
@@ -34,6 +34,7 @@
 #include <sys/un.h>
 #include <time.h>
 
+#include "osi/include/osi.h"
 #include "bta_api.h"
 #include "bta_hl_api.h"
 #include "bta_hl_ci.h"
@@ -368,7 +369,6 @@
     UINT8 app_idx, mcl_idx, mdl_idx;
     btif_hl_mdl_cb_t *p_dcb;
     tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
-    int            r;
     BTIF_TRACE_DEBUG("%s app_id=%d mdl_handle=0x%x data_size=%d",
                       __FUNCTION__,app_id, mdl_handle, data_size);
 
@@ -381,7 +381,9 @@
         if (p_dcb->p_scb) {
             BTIF_TRACE_DEBUG("app_idx=%d mcl_idx=0x%x mdl_idx=0x%x data_size=%d",
                              app_idx, mcl_idx, mdl_idx, data_size);
-            r = send(p_dcb->p_scb->socket_id[1], p_dcb->p_rx_pkt, data_size, 0);
+            ssize_t r;
+            OSI_NO_INTR(r = send(p_dcb->p_scb->socket_id[1], p_dcb->p_rx_pkt,
+                                 data_size, 0));
             if (r == data_size) {
                 BTIF_TRACE_DEBUG("socket send success data_size=%d", data_size);
                 status = BTA_HL_STATUS_OK;
diff --git a/btif/src/btif_hl.cc b/btif/src/btif_hl.cc
index d12d529..5f760e9 100644
--- a/btif/src/btif_hl.cc
+++ b/btif/src/btif_hl.cc
@@ -4655,8 +4655,9 @@
                     osi_free_and_reset((void **)&p_dcb->p_tx_pkt);
                 }
                 p_dcb->p_tx_pkt = (UINT8*)osi_malloc(p_dcb->mtu);
-                int r = (int)recv(p_scb->socket_id[1], p_dcb->p_tx_pkt,
-                                  p_dcb->mtu, MSG_DONTWAIT);
+                ssize_t r;
+                OSI_NO_INTR(r = recv(p_scb->socket_id[1], p_dcb->p_tx_pkt,
+                                     p_dcb->mtu, MSG_DONTWAIT));
                 if (r > 0) {
                     BTIF_TRACE_DEBUG("btif_hl_select_monitor_callback send data r =%d", r);
                     p_dcb->tx_size = r;
@@ -4710,8 +4711,13 @@
 *******************************************************************************/
 static inline int btif_hl_select_wakeup(void){
     char sig_on = btif_hl_signal_select_wakeup;
-    BTIF_TRACE_DEBUG("btif_hl_select_wakeup");
-    return send(signal_fds[1], &sig_on, sizeof(sig_on), 0);
+
+    BTIF_TRACE_DEBUG("%s", __func__);
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(signal_fds[1], &sig_on, sizeof(sig_on), 0));
+
+    return (int)ret;
 }
 
 /*******************************************************************************
@@ -4725,8 +4731,13 @@
 *******************************************************************************/
 static inline int btif_hl_select_close_connected(void){
     char sig_on = btif_hl_signal_select_close_connected;
-    BTIF_TRACE_DEBUG("btif_hl_select_close_connected");
-    return send(signal_fds[1], &sig_on, sizeof(sig_on), 0);
+
+    BTIF_TRACE_DEBUG("%s", __func__);
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(signal_fds[1], &sig_on, sizeof(sig_on), 0));
+
+    return (int)ret;
 }
 
 /*******************************************************************************
@@ -4740,10 +4751,13 @@
 *******************************************************************************/
 static inline int btif_hl_close_select_thread(void)
 {
-    int result = 0;
+    ssize_t result = 0;
     char sig_on = btif_hl_signal_select_exit;
-    BTIF_TRACE_DEBUG("btif_hl_signal_select_exit");
-    result = send(signal_fds[1], &sig_on, sizeof(sig_on), 0);
+
+    BTIF_TRACE_DEBUG("%", __func__);
+
+    OSI_NO_INTR(result = send(signal_fds[1], &sig_on, sizeof(sig_on), 0));
+
     if (btif_is_enabled())
     {
         /* Wait for the select_thread_id to exit if BT is still enabled
@@ -4754,7 +4768,8 @@
         }
     }
     list_free(soc_queue);
-    return result;
+
+    return (int)result;
 }
 
 /*******************************************************************************
@@ -4769,9 +4784,13 @@
 static inline int btif_hl_select_wake_reset(void){
     char sig_recv = 0;
 
-    BTIF_TRACE_DEBUG("btif_hl_select_wake_reset");
-    recv(signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
-    return(int)sig_recv;
+    BTIF_TRACE_DEBUG("%s", __func__);
+
+    ssize_t r;
+    OSI_NO_INTR(r = recv(signal_fds[0], &sig_recv, sizeof(sig_recv),
+                         MSG_WAITALL));
+
+    return (int)sig_recv;
 }
 /*******************************************************************************
 **
@@ -4835,6 +4854,8 @@
         BTIF_TRACE_DEBUG("select unblocked ret=%d", ret);
         if (ret == -1)
         {
+            if (errno == EINTR)
+                continue;
             BTIF_TRACE_DEBUG("select() ret -1, exit the thread");
             btif_hl_thread_cleanup();
             select_thread_id = -1;
diff --git a/btif/src/btif_pan.cc b/btif/src/btif_pan.cc
index 5108fd7..fe6bdbd 100644
--- a/btif/src/btif_pan.cc
+++ b/btif/src/btif_pan.cc
@@ -456,9 +456,10 @@
         memcpy(packet + sizeof(tETH_HDR), buf, len);
 
         /* Send data to network interface */
-        int ret = write(tap_fd, packet, len + sizeof(tETH_HDR));
+        ssize_t ret;
+        OSI_NO_INTR(ret = write(tap_fd, packet, len + sizeof(tETH_HDR)));
         BTIF_TRACE_DEBUG("ret:%d", ret);
-        return ret;
+        return (int)ret;
     }
     return -1;
 
@@ -740,7 +741,9 @@
         // We save it in the congest_packet right away in case we can't deliver it in this
         // attempt.
         if (!btpan_cb.congest_packet_size) {
-            ssize_t ret = read(fd, btpan_cb.congest_packet, sizeof(btpan_cb.congest_packet));
+            ssize_t ret;
+            OSI_NO_INTR(ret = read(fd, btpan_cb.congest_packet,
+                                   sizeof(btpan_cb.congest_packet)));
             switch (ret) {
                 case -1:
                     BTIF_TRACE_ERROR("%s unable to read from driver: %s", __func__, strerror(errno));
diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc
index f378db9..275e50f 100644
--- a/btif/src/btif_rc.cc
+++ b/btif/src/btif_rc.cc
@@ -316,7 +316,9 @@
     event.code  = code;
     event.value = value;
 
-    return write(fd, &event, sizeof(event));
+    ssize_t ret;
+    OSI_NO_INTR(ret = write(fd, &event, sizeof(event)));
+    return (int)ret;
 }
 
 void send_key (int fd, uint16_t key, int pressed)
@@ -373,7 +375,9 @@
     dev.id.product = 0x0000;
     dev.id.version = 0x0000;
 
-    if (write(fd, &dev, sizeof(dev)) < 0) {
+    ssize_t ret;
+    OSI_NO_INTR(ret = write(fd, &dev, sizeof(dev)));
+    if (ret < 0) {
         BTIF_TRACE_ERROR("%s Unable to write device information", __FUNCTION__);
         close(fd);
         return -1;
@@ -4232,10 +4236,7 @@
     delay.tv_sec = timeout_ms / 1000;
     delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
 
-    int err;
-    do {
-        err = nanosleep(&delay, &delay);
-    } while (err == -1 && errno == EINTR);
+    OSI_NO_INTR(nanosleep(&delay, &delay));
 }
 
 static bool absolute_volume_disabled() {
diff --git a/btif/src/btif_sock_l2cap.cc b/btif/src/btif_sock_l2cap.cc
index 5438405..2e8a588 100644
--- a/btif/src/btif_sock_l2cap.cc
+++ b/btif/src/btif_sock_l2cap.cc
@@ -998,7 +998,9 @@
     uint32_t len;
 
     while (packet_get_head_l(sock, &buf, &len)) {
-        int sent = send(sock->our_fd, buf, len, MSG_DONTWAIT);
+        ssize_t sent;
+        OSI_NO_INTR(sent = send(sock->our_fd, buf, len, MSG_DONTWAIT));
+        int saved_errno = errno;
 
         if (sent == (signed)len)
             osi_free(buf);
@@ -1011,7 +1013,7 @@
         else {
             packet_put_head_l(sock, buf, len);
             osi_free(buf);
-            return errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN;
+            return saved_errno == EWOULDBLOCK || saved_errno == EAGAIN;
         }
     }
 
@@ -1055,8 +1057,9 @@
                      * be wrong
                      * UPDATE: Since we are responsible for freeing the buffer in the
                      * write_complete_ind, it is OK to use malloc. */
-                    int count = recv(fd, buffer, L2CAP_MAX_SDU_LENGTH,
-                                     MSG_NOSIGNAL | MSG_DONTWAIT);
+                    ssize_t count;
+                    OSI_NO_INTR(count = recv(fd, buffer, L2CAP_MAX_SDU_LENGTH,
+                                             MSG_NOSIGNAL | MSG_DONTWAIT));
                     APPL_TRACE_DEBUG("btsock_l2cap_signaled - %d bytes received from socket",
                                      count);
 
diff --git a/btif/src/btif_sock_rfc.cc b/btif/src/btif_sock_rfc.cc
index cf40af3..6c5ea7f 100644
--- a/btif/src/btif_sock_rfc.cc
+++ b/btif/src/btif_sock_rfc.cc
@@ -747,10 +747,12 @@
   if (p_buf->len == 0)
     return SENT_ALL;
 
-  ssize_t sent = send(fd, p_buf->data + p_buf->offset, p_buf->len, MSG_DONTWAIT);
+  ssize_t sent;
+  OSI_NO_INTR(sent = send(fd, p_buf->data + p_buf->offset, p_buf->len,
+                          MSG_DONTWAIT));
 
   if (sent == -1) {
-    if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR)
+    if (errno == EAGAIN || errno == EWOULDBLOCK)
       return SENT_NONE;
     LOG_ERROR(LOG_TAG, "%s error writing RFCOMM data back to app: %s", __func__, strerror(errno));
     return SENT_FAILED;
@@ -909,12 +911,13 @@
 
   uint32_t id = (uintptr_t)user_data;
   int ret = false;
-  int received;
   rfc_slot_t *slot = find_rfc_slot_by_id(id);
   if (!slot)
     goto out;
 
-  received = recv(slot->fd, buf, size, 0);
+  ssize_t received;
+  OSI_NO_INTR(received = recv(slot->fd, buf, size, 0));
+
   if(received == size) {
     ret = true;
   } else {
diff --git a/btif/src/btif_sock_thread.cc b/btif/src/btif_sock_thread.cc
index 9f12b4c..889c259 100644
--- a/btif/src/btif_sock_thread.cc
+++ b/btif/src/btif_sock_thread.cc
@@ -263,7 +263,11 @@
     }
     sock_cmd_t cmd = {CMD_ADD_FD, fd, type, flags, user_id};
     APPL_TRACE_DEBUG("adding fd:%d, flags:0x%x", fd, flags);
-    return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0));
+
+    return ret == sizeof(cmd);
 }
 
 bool btsock_thread_remove_fd_and_close(int thread_handle, int fd)
@@ -280,7 +284,11 @@
     }
 
     sock_cmd_t cmd = {CMD_REMOVE_FD, fd, 0, 0, 0};
-    return send(ts[thread_handle].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(ts[thread_handle].cmd_fdw, &cmd, sizeof(cmd), 0));
+
+    return ret == sizeof(cmd);
 }
 
 int btsock_thread_post_cmd(int h, int type, const unsigned char* data, int size, uint32_t user_id)
@@ -314,7 +322,11 @@
             return FALSE;
         }
     }
-    return send(ts[h].cmd_fdw, cmd_send, size_send, 0) == size_send;
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(ts[h].cmd_fdw, cmd_send, size_send, 0));
+
+    return ret == size_send;
 }
 int btsock_thread_wakeup(int h)
 {
@@ -329,7 +341,11 @@
         return FALSE;
     }
     sock_cmd_t cmd = {CMD_WAKEUP, 0, 0, 0, 0};
-    return send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd);
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0));
+
+    return ret == sizeof(cmd);
 }
 int btsock_thread_exit(int h)
 {
@@ -344,8 +360,11 @@
         return FALSE;
     }
     sock_cmd_t cmd = {CMD_EXIT, 0, 0, 0, 0};
-    if(send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0) == sizeof(cmd))
-    {
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(ts[h].cmd_fdw, &cmd, sizeof(cmd), 0));
+
+    if (ret == sizeof(cmd)) {
         pthread_join(ts[h].thread_id, 0);
         pthread_mutex_lock(&thread_slot_lock);
         free_thread_slot(h);
@@ -439,7 +458,11 @@
 {
     sock_cmd_t cmd = {-1, 0, 0, 0, 0};
     int fd = ts[h].cmd_fdr;
-    if(recv(fd, &cmd, sizeof(cmd), MSG_WAITALL) != sizeof(cmd))
+
+    ssize_t ret;
+    OSI_NO_INTR(ret = recv(fd, &cmd, sizeof(cmd), MSG_WAITALL));
+
+    if (ret != sizeof(cmd))
     {
         APPL_TRACE_ERROR("recv cmd errno:%d", errno);
         return FALSE;
@@ -546,7 +569,8 @@
     for(;;)
     {
         prepare_poll_fds(h, pfds);
-        int ret = poll(pfds, ts[h].poll_count, -1);
+        int ret;
+        OSI_NO_INTR(ret = poll(pfds, ts[h].poll_count, -1));
         if(ret == -1)
         {
             APPL_TRACE_ERROR("poll ret -1, exit the thread, errno:%d, err:%s", errno, strerror(errno));
diff --git a/btif/src/btif_sock_util.cc b/btif/src/btif_sock_util.cc
index 3d16929..19385f0 100644
--- a/btif/src/btif_sock_util.cc
+++ b/btif/src/btif_sock_util.cc
@@ -58,11 +58,11 @@
 int sock_send_all(int sock_fd, const uint8_t* buf, int len)
 {
     int s = len;
-    int ret;
+
     while(s)
     {
-        do ret = send(sock_fd, buf, s, 0);
-        while(ret < 0 && errno == EINTR);
+        ssize_t ret;
+        OSI_NO_INTR(ret = send(sock_fd, buf, s, 0));
         if(ret <= 0)
         {
             BTIF_TRACE_ERROR("sock fd:%d send errno:%d, ret:%d", sock_fd, errno, ret);
@@ -76,11 +76,11 @@
 int sock_recv_all(int sock_fd, uint8_t* buf, int len)
 {
     int r = len;
-    int ret = -1;
+
     while(r)
     {
-        do ret = recv(sock_fd, buf, r, MSG_WAITALL);
-        while(ret < 0 && errno == EINTR);
+        ssize_t ret;
+        OSI_NO_INTR(ret = recv(sock_fd, buf, r, MSG_WAITALL));
         if(ret <= 0)
         {
             BTIF_TRACE_ERROR("sock fd:%d recv errno:%d, ret:%d", sock_fd, errno, ret);
@@ -94,7 +94,6 @@
 
 int sock_send_fd(int sock_fd, const uint8_t* buf, int len, int send_fd)
 {
-    ssize_t ret;
     struct msghdr msg;
     unsigned char *buffer = (unsigned char *)buf;
     memset(&msg, 0, sizeof(msg));
@@ -126,10 +125,8 @@
         msg.msg_iov = &iv;
         msg.msg_iovlen = 1;
 
-        do {
-            ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL);
-        } while (ret < 0 && errno == EINTR);
-
+        ssize_t ret;
+        OSI_NO_INTR(ret = sendmsg(sock_fd, &msg, MSG_NOSIGNAL));
         if (ret < 0) {
             BTIF_TRACE_ERROR("fd:%d, send_fd:%d, sendmsg ret:%d, errno:%d, %s",
                               sock_fd, send_fd, (int)ret, errno, strerror(errno));
diff --git a/hci/src/btsnoop_net.c b/hci/src/btsnoop_net.c
index e0c1ccf..0bfad4e 100644
--- a/hci/src/btsnoop_net.c
+++ b/hci/src/btsnoop_net.c
@@ -78,7 +78,10 @@
 
   pthread_mutex_lock(&client_socket_lock_);
   if (client_socket_ != -1) {
-    if (send(client_socket_, data, length, 0) == -1 && errno == ECONNRESET) {
+    ssize_t ret;
+    OSI_NO_INTR(ret = send(client_socket_, data, length, 0));
+
+    if (ret == -1 && errno == ECONNRESET) {
       safe_close_(&client_socket_);
     }
   }
@@ -116,7 +119,8 @@
   }
 
   for (;;) {
-    int client_socket = accept(listen_socket_, NULL, NULL);
+    int client_socket;
+    OSI_NO_INTR(client_socket = accept(listen_socket_, NULL, NULL));
     if (client_socket == -1) {
       if (errno == EINVAL || errno == EBADF) {
         break;
@@ -130,7 +134,8 @@
     pthread_mutex_lock(&client_socket_lock_);
     safe_close_(&client_socket_);
     client_socket_ = client_socket;
-    send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0);
+
+    OSI_NO_INTR(send(client_socket_, "btsnoop\0\0\0\0\1\0\0\x3\xea", 16, 0));
     pthread_mutex_unlock(&client_socket_lock_);
   }
 
diff --git a/hci/src/hci_hal_h4.c b/hci/src/hci_hal_h4.c
index 651579c..062b6c0 100644
--- a/hci/src/hci_hal_h4.c
+++ b/hci/src/hci_hal_h4.c
@@ -154,7 +154,8 @@
 
   uint16_t transmitted_length = 0;
   while (length > 0) {
-    ssize_t ret = write(uart_fd, data + transmitted_length, length);
+    ssize_t ret;
+    OSI_NO_INTR(ret = write(uart_fd, data + transmitted_length, length));
     switch (ret) {
       case -1:
         LOG_ERROR(LOG_TAG, "In %s, error writing to the uart serial port: %s", __func__, strerror(errno));
diff --git a/hci/src/hci_hal_mct.c b/hci/src/hci_hal_mct.c
index c242702..669a9f8 100644
--- a/hci/src/hci_hal_mct.c
+++ b/hci/src/hci_hal_mct.c
@@ -160,7 +160,8 @@
 
   uint16_t transmitted_length = 0;
   while (length > 0) {
-    ssize_t ret = write(fd, data + transmitted_length, length);
+    ssize_t ret;
+    OSI_NO_INTR(ret = write(fd, data + transmitted_length, length));
     switch (ret) {
       case -1:
         LOG_ERROR(LOG_TAG, "In %s, error writing to the serial port with fd %d: %s", __func__, fd, strerror(errno));
diff --git a/osi/include/osi.h b/osi/include/osi.h
index ed8fc2a..966c617 100644
--- a/osi/include/osi.h
+++ b/osi/include/osi.h
@@ -64,6 +64,9 @@
 // Effort is made for this to come from a real random source.
 int osi_rand(void);
 
+// Re-run |fn| system call until the system call doesn't cause EINTR.
+#define OSI_NO_INTR(fn)  do {} while ((fn) == -1 && errno == EINTR)
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/osi/include/socket.h b/osi/include/socket.h
index ac49921..b27e681 100644
--- a/osi/include/socket.h
+++ b/osi/include/socket.h
@@ -62,20 +62,24 @@
 // block. This function returns a positive integer representing the number
 // of bytes copied into |buf| on success, 0 if the socket has disconnected,
 // and -1 on error. This function may return a value less than |count| if not
-// enough data is currently available. If this function returns -1, errno will also
-// be set (see recv(2) for possible errno values). If there were no bytes available
-// to be read, this function returns -1 and sets errno to EWOULDBLOCK. Neither
-// |socket| nor |buf| may be NULL.
+// enough data is currently available. If this function returns -1, errno will
+// also be set (see recv(2) for possible errno values). However, if the reading
+// system call was interrupted with errno of EINTR, the read operation is
+// restarted internally without propagating EINTR back to the caller. If there
+// were no bytes available to be read, this function returns -1 and sets errno
+// to EWOULDBLOCK. Neither |socket| nor |buf| may be NULL.
 ssize_t socket_read(const socket_t *socket, void *buf, size_t count);
 
 // Writes up to |count| bytes from |buf| into |socket|. This function will not
 // block. Returns a positive integer representing the number of bytes written
-// to |socket| on success, 0 if the socket has disconnected, and -1 on error. This
-// function may return a value less than |count| if writing more bytes would result
-// in blocking. If this function returns -1, errno will also be set (see send(2) for
-// possible errno values). If no bytes could be written without blocking, this
-// function will return -1 and set errno to EWOULDBLOCK. Neither |socket| nor |buf|
-// may be NULL.
+// to |socket| on success, 0 if the socket has disconnected, and -1 on error.
+// This function may return a value less than |count| if writing more bytes
+// would result in blocking. If this function returns -1, errno will also be
+// set (see send(2) for possible errno values). However, if the writing system
+// call was interrupted with errno of EINTR, the write operation is restarted
+// internally without propagating EINTR back to the caller. If no bytes could
+// be written without blocking, this function will return -1 and set errno to
+// EWOULDBLOCK. Neither |socket| nor |buf| may be NULL.
 ssize_t socket_write(const socket_t *socket, const void *buf, size_t count);
 
 // This function performs the same write operation as |socket_write| and also
diff --git a/osi/src/eager_reader.c b/osi/src/eager_reader.c
index 044ee81..07a944c 100644
--- a/osi/src/eager_reader.c
+++ b/osi/src/eager_reader.c
@@ -215,15 +215,23 @@
   assert(reader != NULL);
 
   fd_set read_fds;
-  FD_ZERO(&read_fds);
-  FD_SET(reader->bytes_available_fd, &read_fds);
 
-  // Immediate timeout
-  struct timeval timeout;
-  timeout.tv_sec = 0;
-  timeout.tv_usec = 0;
+  for (;;) {
+    FD_ZERO(&read_fds);
+    FD_SET(reader->bytes_available_fd, &read_fds);
 
-  select(reader->bytes_available_fd + 1, &read_fds, NULL, NULL, &timeout);
+    // Immediate timeout
+    struct timeval timeout;
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+
+    int ret = select(reader->bytes_available_fd + 1, &read_fds, NULL, NULL,
+                     &timeout);
+    if (ret == -1 && errno == EINTR)
+      continue;
+    break;
+  }
+
   return FD_ISSET(reader->bytes_available_fd, &read_fds);
 }
 
@@ -239,7 +247,9 @@
   buffer->length = 0;
   buffer->offset = 0;
 
-  int bytes_read = read(reader->inbound_fd, buffer->data, reader->buffer_size);
+  ssize_t bytes_read;
+  OSI_NO_INTR(bytes_read = read(reader->inbound_fd, buffer->data,
+                                reader->buffer_size));
   if (bytes_read > 0) {
     // Save the data for later
     buffer->length = bytes_read;
diff --git a/osi/src/metrics.cc b/osi/src/metrics.cc
index a99200b..064f99e 100644
--- a/osi/src/metrics.cc
+++ b/osi/src/metrics.cc
@@ -196,7 +196,9 @@
   std::string protoBase64;
   base::Base64Encode(serialized, &protoBase64);
 
-  if (write(fd, protoBase64.c_str(), protoBase64.size()) == -1) {
+  ssize_t ret;
+  OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
+  if (ret == -1) {
     LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__,
               strerror(errno), errno);
   }
@@ -215,9 +217,10 @@
   }
   log_lock.unlock();
 
-  if (write(fd, pretty_output.c_str(), pretty_output.size()) == -1) {
+  ssize_t ret;
+  OSI_NO_INTR(ret = write(fd, pretty_output.c_str(), pretty_output.size()));
+  if (ret == -1) {
     LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__,
               strerror(errno), errno);
   }
-
 }
diff --git a/osi/src/reactor.c b/osi/src/reactor.c
index 7bab5e4..7388d52 100644
--- a/osi/src/reactor.c
+++ b/osi/src/reactor.c
@@ -237,10 +237,7 @@
     pthread_mutex_unlock(&reactor->list_lock);
 
     int ret;
-    do {
-      ret = epoll_wait(reactor->epoll_fd, events, MAX_EVENTS, -1);
-    } while (ret == -1 && errno == EINTR);
-
+    OSI_NO_INTR(ret = epoll_wait(reactor->epoll_fd, events, MAX_EVENTS, -1));
     if (ret == -1) {
       LOG_ERROR(LOG_TAG, "%s error in epoll_wait: %s", __func__, strerror(errno));
       reactor->is_running = false;
diff --git a/osi/src/socket.c b/osi/src/socket.c
index 80813f5..4ebb3b8 100644
--- a/osi/src/socket.c
+++ b/osi/src/socket.c
@@ -113,7 +113,8 @@
 socket_t *socket_accept(const socket_t *socket) {
   assert(socket != NULL);
 
-  int fd = accept(socket->fd, NULL, NULL);
+  int fd;
+  OSI_NO_INTR(fd = accept(socket->fd, NULL, NULL));
   if (fd == INVALID_FD) {
     LOG_ERROR(LOG_TAG, "%s unable to accept socket: %s", __func__, strerror(errno));
     return NULL;
@@ -129,14 +130,20 @@
   assert(socket != NULL);
   assert(buf != NULL);
 
-  return recv(socket->fd, buf, count, MSG_DONTWAIT);
+  ssize_t ret;
+  OSI_NO_INTR(ret = recv(socket->fd, buf, count, MSG_DONTWAIT));
+
+  return ret;
 }
 
 ssize_t socket_write(const socket_t *socket, const void *buf, size_t count) {
   assert(socket != NULL);
   assert(buf != NULL);
 
-  return send(socket->fd, buf, count, MSG_DONTWAIT);
+  ssize_t ret;
+  OSI_NO_INTR(ret = send(socket->fd, buf, count, MSG_DONTWAIT));
+
+  return ret;
 }
 
 ssize_t socket_write_and_transfer_fd(const socket_t *socket, const void *buf, size_t count, int fd) {
@@ -166,7 +173,9 @@
   header->cmsg_len = CMSG_LEN(sizeof(int));
   *(int *)CMSG_DATA(header) = fd;
 
-  ssize_t ret = sendmsg(socket->fd, &msg, MSG_DONTWAIT);
+  ssize_t ret;
+  OSI_NO_INTR(ret = sendmsg(socket->fd, &msg, MSG_DONTWAIT));
+
   close(fd);
   return ret;
 }
diff --git a/osi/src/socket_utils/socket_local_client.c b/osi/src/socket_utils/socket_local_client.c
index ccfe743..73a828c 100644
--- a/osi/src/socket_utils/socket_local_client.c
+++ b/osi/src/socket_utils/socket_local_client.c
@@ -121,7 +121,8 @@
     goto error;
   }
 
-  if (connect(fd, (struct sockaddr *)&addr, alen) < 0) {
+  OSI_NO_INTR(err = connect(fd, (struct sockaddr *)&addr, alen));
+  if (err < 0) {
     goto error;
   }
 
diff --git a/service/gatt_server_old.cc b/service/gatt_server_old.cc
index 204a441..f775be9 100644
--- a/service/gatt_server_old.cc
+++ b/service/gatt_server_old.cc
@@ -231,8 +231,9 @@
     // This is a single frame characteristic write.
     // Notify upwards because we're done now.
     const bluetooth::UUID::UUID128Bit &attr_uuid = ch.uuid.GetFullBigEndian();
-    int status = write(g_internal->pipefd[kPipeWriteEnd], attr_uuid.data(),
-                       attr_uuid.size());
+    ssize_t status;
+    OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd],
+                               attr_uuid.data(), attr_uuid.size()));
     if (-1 == status)
       LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
   } else {
@@ -273,8 +274,9 @@
   // Communicate the attribute UUID as notification of a write update.
   const bluetooth::UUID::UUID128Bit uuid =
       g_internal->last_write.GetFullBigEndian();
-  int status = write(g_internal->pipefd[kPipeWriteEnd],
-                     uuid.data(), uuid.size());
+  ssize_t status;
+  OSI_NO_INTR(status = write(g_internal->pipefd[kPipeWriteEnd], uuid.data(),
+                             uuid.size()));
   if (-1 == status)
     LOG_ERROR(LOG_TAG, "%s: write failed: %s", __func__, strerror(errno));
 }
diff --git a/service/ipc/linux_ipc_host.cc b/service/ipc/linux_ipc_host.cc
index f0ca34c..a3176a9 100644
--- a/service/ipc/linux_ipc_host.cc
+++ b/service/ipc/linux_ipc_host.cc
@@ -33,6 +33,7 @@
 #include <base/strings/string_number_conversions.h>
 #include <base/strings/string_split.h>
 
+#include "osi/include/osi.h"
 #include "osi/include/log.h"
 #include "service/adapter.h"
 
@@ -248,7 +249,10 @@
 
 bool LinuxIPCHost::OnMessage() {
   std::string ipc_msg;
-  int size = recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0, MSG_PEEK | MSG_TRUNC);
+  ssize_t size;
+
+  OSI_NO_INTR(size = recv(pfds_[kFdIpc].fd, &ipc_msg[0], 0,
+                          MSG_PEEK | MSG_TRUNC));
   if (-1 == size) {
     LOG_ERROR(LOG_TAG, "Error reading datagram size: %s", strerror(errno));
     return false;
@@ -258,7 +262,7 @@
   }
 
   ipc_msg.resize(size);
-  size = read(pfds_[kFdIpc].fd, &ipc_msg[0], ipc_msg.size());
+  OSI_NO_INTR(size = read(pfds_[kFdIpc].fd, &ipc_msg[0], ipc_msg.size()));
   if (-1 == size) {
     LOG_ERROR(LOG_TAG, "Error reading IPC: %s", strerror(errno));
     return false;
@@ -306,7 +310,9 @@
 
 bool LinuxIPCHost::OnGattWrite() {
   UUID::UUID128Bit id;
-  int r = read(pfds_[kFdGatt].fd, id.data(), id.size());
+  ssize_t r;
+
+  OSI_NO_INTR(r = read(pfds_[kFdGatt].fd, id.data(), id.size()));
   if (r != id.size()) {
     LOG_ERROR(LOG_TAG, "Error reading GATT attribute ID");
     return false;
@@ -325,7 +331,7 @@
   transmit += "|" + base::HexEncode(id.data(), id.size());
   transmit += "|" + encoded_value;
 
-  r = write(pfds_[kFdIpc].fd, transmit.data(), transmit.size());
+  OSI_NO_INTR(r = write(pfds_[kFdIpc].fd, transmit.data(), transmit.size()));
   if (-1 == r) {
     LOG_ERROR(LOG_TAG, "Error replying to IPC: %s", strerror(errno));
     return false;
diff --git a/tools/hci/main.c b/tools/hci/main.c
index cc2fa7a..4fbb457 100644
--- a/tools/hci/main.c
+++ b/tools/hci/main.c
@@ -176,7 +176,10 @@
   addr.sin_family = AF_INET;
   addr.sin_addr.s_addr = htonl(0x7F000001);
   addr.sin_port = htons(8873);
-  if (connect(sock, (const struct sockaddr *)&addr, sizeof(addr)) == -1)
+  int ret;
+  OSI_NO_INTR(ret = connect(sock, (const struct sockaddr *)&addr,
+                            sizeof(addr)));
+  if (ret == -1)
     goto error;
 
   if (send(sock, &type, 1, 0) != 1)
diff --git a/udrv/ulinux/uipc.c b/udrv/ulinux/uipc.c
index 4256aed..c9ff0f1 100644
--- a/udrv/ulinux/uipc.c
+++ b/udrv/ulinux/uipc.c
@@ -44,6 +44,7 @@
 #include "bt_types.h"
 #include "bt_utils.h"
 #include "bt_common.h"
+#include "osi/include/osi.h"
 #include "osi/include/socket_utils/sockets.h"
 #include "uipc.h"
 
@@ -179,7 +180,9 @@
     pfd.fd = sfd;
     pfd.events = POLLIN;
 
-    if (poll(&pfd, 1, 0) == 0)
+    int poll_ret;
+    OSI_NO_INTR(poll_ret = poll(&pfd, 1, 0));
+    if (poll_ret == 0)
     {
         BTIF_TRACE_WARNING("accept poll timeout");
         return -1;
@@ -187,8 +190,8 @@
 
     //BTIF_TRACE_EVENT("poll revents 0x%x", pfd.revents);
 
-    if ((fd = accept(sfd, (struct sockaddr *)&remote, &len)) == -1)
-    {
+    OSI_NO_INTR(fd = accept(sfd, (struct sockaddr *)&remote, &len));
+    if (fd == -1) {
          BTIF_TRACE_ERROR("sock accept failed (%s)", strerror(errno));
          return -1;
     }
@@ -324,8 +327,8 @@
     if (SAFE_FD_ISSET(uipc_main.signal_fds[0], &uipc_main.read_set))
     {
         char sig_recv = 0;
-        //BTIF_TRACE_EVENT("UIPC INTERRUPT");
-        recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv), MSG_WAITALL);
+        OSI_NO_INTR(recv(uipc_main.signal_fds[0], &sig_recv, sizeof(sig_recv),
+                         MSG_WAITALL));
     }
 }
 
@@ -333,7 +336,8 @@
 {
     char sig_on = 1;
     BTIF_TRACE_EVENT("UIPC SEND WAKE UP");
-    send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0);
+
+    OSI_NO_INTR(send(uipc_main.signal_fds[1], &sig_on, sizeof(sig_on), 0));
 }
 
 static int uipc_setup_server_locked(tUIPC_CH_ID ch_id, char *name, tUIPC_RCV_CBACK *cback)
@@ -376,7 +380,6 @@
 {
     char buf[UIPC_FLUSH_BUFFER_SIZE];
     struct pollfd pfd;
-    int ret;
 
     pfd.events = POLLIN;
     pfd.fd = uipc_main.ch[ch_id].fd;
@@ -389,10 +392,10 @@
 
     while (1)
     {
-        ret = poll(&pfd, 1, 1);
+        int ret;
+        OSI_NO_INTR(ret = poll(&pfd, 1, 1));
         BTIF_TRACE_VERBOSE("%s() - polling fd %d, revents: 0x%x, ret %d",
                 __FUNCTION__, pfd.fd, pfd.revents, ret);
-
         if (pfd.revents & (POLLERR|POLLHUP))
         {
             BTIF_TRACE_WARNING("%s() - POLLERR or POLLHUP. Exiting", __FUNCTION__);
@@ -500,14 +503,13 @@
 
         result = select(uipc_main.max_fd+1, &uipc_main.read_set, NULL, NULL, NULL);
 
-        if (result == 0)
-        {
+        if (result == 0) {
             BTIF_TRACE_EVENT("select timeout");
             continue;
         }
-        else if (result < 0)
-        {
-            BTIF_TRACE_EVENT("select failed %s", strerror(errno));
+        if (result < 0) {
+            if (errno != EINTR)
+                BTIF_TRACE_EVENT("select failed %s", strerror(errno));
             continue;
         }
 
@@ -686,8 +688,9 @@
 
     UIPC_LOCK();
 
-    if (write(uipc_main.ch[ch_id].fd, p_buf, msglen) < 0)
-    {
+    ssize_t ret;
+    OSI_NO_INTR(ret = write(uipc_main.ch[ch_id].fd, p_buf, msglen));
+    if (ret < 0) {
         BTIF_TRACE_ERROR("failed to write (%s)", strerror(errno));
     }
 
@@ -708,7 +711,6 @@
 
 UINT32 UIPC_Read(tUIPC_CH_ID ch_id, UINT16 *p_msg_evt, UINT8 *p_buf, UINT32 len)
 {
-    int n;
     int n_read = 0;
     int fd = uipc_main.ch[ch_id].fd;
     struct pollfd pfd;
@@ -736,7 +738,11 @@
 
         /* make sure there is data prior to attempting read to avoid blocking
            a read for more than poll timeout */
-        if (poll(&pfd, 1, uipc_main.ch[ch_id].read_poll_tmo_ms) == 0)
+
+        int poll_ret;
+        OSI_NO_INTR(poll_ret = poll(&pfd, 1,
+                                    uipc_main.ch[ch_id].read_poll_tmo_ms));
+        if (poll_ret == 0)
         {
             BTIF_TRACE_WARNING("poll timeout (%d ms)", uipc_main.ch[ch_id].read_poll_tmo_ms);
             break;
@@ -753,7 +759,8 @@
             return 0;
         }
 
-        n = recv(fd, p_buf+n_read, len-n_read, 0);
+        ssize_t n;
+        OSI_NO_INTR(n = recv(fd, p_buf+n_read, len-n_read, 0));
 
         //BTIF_TRACE_EVENT("read %d bytes", n);
 
diff --git a/vendor_libs/linux/bt_vendor_linux.c b/vendor_libs/linux/bt_vendor_linux.c
index 368f3c6..34876fc 100644
--- a/vendor_libs/linux/bt_vendor_linux.c
+++ b/vendor_libs/linux/bt_vendor_linux.c
@@ -180,14 +180,18 @@
   ev.opcode = MGMT_OP_INDEX_LIST;
   ev.index = HCI_DEV_NONE;
   ev.len = 0;
-  if (write(fd, &ev, 6) != 6) {
+
+  ssize_t wrote;
+  OSI_NO_INTR(wrote = write(fd, &ev, 6));
+  if (wrote != 6) {
     LOG_ERROR(LOG_TAG, "Unable to write mgmt command: %s", strerror(errno));
     ret = -1;
     goto end;
   }
 
   while (1) {
-    int n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT);
+    int n;
+    OSI_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT));
     if (n == -1) {
       LOG_ERROR(LOG_TAG, "Poll error: %s", strerror(errno));
       ret = -1;
@@ -273,7 +277,7 @@
 static int bt_vendor_rfkill(int block)
 {
   struct rfkill_event event;
-  int fd, len;
+  int fd;
 
   LOG_INFO(LOG_TAG, "%s", __func__);
 
@@ -289,7 +293,8 @@
   event.hard = block;
   event.soft = block;
 
-  len = write(fd, &event, sizeof(event));
+  ssize_t len;
+  OSI_NO_INTR(len = write(fd, &event, sizeof(event)));
   if (len < 0) {
     LOG_ERROR(LOG_TAG, "Failed to change rfkill state");
     close(fd);