From 08356b84fa39f0ca1860d90e2fadefc9fc1468f7 Mon Sep 17 00:00:00 2001 From: David Vossel Date: Wed, 12 Mar 2014 14:05:13 -0400 Subject: [PATCH] Fix: ipcc: Properly timeout during recv when timeout value is provided --- lib/ipc_socket.c | 17 ++++++++++++----- lib/ipcc.c | 21 +++++++++++++++++++-- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/lib/ipc_socket.c b/lib/ipc_socket.c index 5b02b3a..084a445 100644 --- a/lib/ipc_socket.c +++ b/lib/ipc_socket.c @@ -387,13 +387,20 @@ retry_peek: MSG_NOSIGNAL | MSG_PEEK); if (result == -1) { - if (errno == EAGAIN && (time_waited < timeout || timeout == -1)) { - result = qb_ipc_us_ready(one_way, NULL, - time_to_wait, POLLIN); + if (errno != EAGAIN) { + return -errno; + } + + /* check to see if we have enough time left to try again */ + if (time_waited < timeout || timeout == -1) { + result = qb_ipc_us_ready(one_way, NULL, time_to_wait, POLLIN); + if (qb_ipc_us_sock_error_is_disconnected(result)) { + return result; + } time_waited += time_to_wait; goto retry_peek; - } else { - return -errno; + } else if (time_waited >= timeout) { + return -ETIMEDOUT; } } if (result >= sizeof(struct qb_ipc_request_header)) { diff --git a/lib/ipcc.c b/lib/ipcc.c index 061cb1c..f9042c8 100644 --- a/lib/ipcc.c +++ b/lib/ipcc.c @@ -118,8 +118,13 @@ _check_connection_state_with(struct qb_ipcc_connection * c, int32_t res, res2, "(from socket) as a disconnect"); c->is_connected = QB_FALSE; + res = res2; + } else if (res != -ETIMEDOUT) { + /* if the result we're checking against is a TIMEOUT error. + * don't override that result with another error that does + * not imply a disconnect */ + res = res2; } - res = res2; } return res; } @@ -260,15 +265,27 @@ qb_ipcc_recv(struct qb_ipcc_connection * c, void *msg_ptr, size_t msg_len, int32_t ms_timeout) { int32_t res = 0; + int32_t connect_res = 0; if (c == NULL) { return -EINVAL; } res = c->funcs.recv(&c->response, msg_ptr, msg_len, ms_timeout); - return _check_connection_state_with(c, res, + if (res >= 0) { + return res; + } + + /* if we didn't get a msg, check connection state */ + connect_res = _check_connection_state_with(c, res, _response_sock_one_way_get(c), ms_timeout, POLLIN); + + /* only report the connection state check result if an error is returned. */ + if (connect_res < 0) { + return connect_res; + } + return res; } ssize_t