From 9dea9384ee4b42df99d0952d01115c9afe09d25b Mon Sep 17 00:00:00 2001 From: Dmitrii Kuvaiskii Date: Sun, 7 Jul 2019 21:13:31 -0700 Subject: [PATCH] [LibOS] Handle corner-cases during {send,receive}_ipc_message This commit adds additional logic around DkStreamWrite() and DkStreamRead() in send_ipc_message() and receive_ipc_message() respectively: interrupts and partial reads/writes are handled correctly. --- LibOS/shim/src/ipc/shim_ipc.c | 25 +++++++++++++++++-------- LibOS/shim/src/ipc/shim_ipc_helper.c | 9 +++++---- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/LibOS/shim/src/ipc/shim_ipc.c b/LibOS/shim/src/ipc/shim_ipc.c index 8cde2016..f623c45e 100644 --- a/LibOS/shim/src/ipc/shim_ipc.c +++ b/LibOS/shim/src/ipc/shim_ipc.c @@ -257,15 +257,24 @@ int send_ipc_message(struct shim_ipc_msg* msg, struct shim_ipc_port* port) { msg->src = cur_process.vmid; debug("Sending ipc message to port %p (handle %p)\n", port, port->pal_handle); - /* TODO: Handle benign EINTR case? */ - /* TODO: Add while-loop to send all msg */ - int ret = DkStreamWrite(port->pal_handle, 0, msg->size, msg, NULL); + size_t total_bytes = msg->size; + size_t bytes = 0; - if (ret == 0 && PAL_NATIVE_ERRNO) { - debug("Port %p (handle %p) was removed during sending\n", port, port->pal_handle); - del_ipc_port_fini(port, -ECHILD); - return -PAL_ERRNO; - } + do { + size_t ret = DkStreamWrite(port->pal_handle, 0, total_bytes - bytes, + (void *)msg + bytes, NULL); + + if (!ret) { + if (PAL_ERRNO == EINTR || PAL_ERRNO == EAGAIN || PAL_ERRNO == EWOULDBLOCK) + continue; + + debug("Port %p (handle %p) was removed during sending\n", port, port->pal_handle); + del_ipc_port_fini(port, -ECHILD); + return -PAL_ERRNO; + } + + bytes += ret; + } while (bytes < total_bytes); return 0; } diff --git a/LibOS/shim/src/ipc/shim_ipc_helper.c b/LibOS/shim/src/ipc/shim_ipc_helper.c index df6794cd..6612dc4f 100644 --- a/LibOS/shim/src/ipc/shim_ipc_helper.c +++ b/LibOS/shim/src/ipc/shim_ipc_helper.c @@ -495,12 +495,13 @@ static int receive_ipc_message(struct shim_ipc_port* port) { msg = tmp_buf; } - /* TODO: Add while-loop to receive all msg */ int read = DkStreamRead(port->pal_handle, /*offset*/ 0, expected_size - bytes + readahead, (void *) msg + bytes, NULL, 0); - if (read == 0) { - /* TODO: Handle benign EINTR case? */ + if (!read) { + if (PAL_ERRNO == EINTR || PAL_ERRNO == EAGAIN || PAL_ERRNO == EWOULDBLOCK) + continue; + debug("Port %p (handle %p) closed while receiving IPC message\n", port, port->pal_handle); del_ipc_port_fini(port, -ECHILD); ret = -PAL_ERRNO; @@ -639,7 +640,7 @@ noreturn static void shim_ipc_helper(void* dummy) { if (DkStreamAttributesQueryByHandle(polled_port->pal_handle, &attr)) { /* can read on this port, so receive messages */ if (attr.readable) { - /* TODO: IPC helper thread does not handle failures currently */ + /* NOTE: IPC helper thread does not handle failures currently */ receive_ipc_message(polled_port); }