It needs to only recv the size of this message, else we recv more than one message and effectively drop messages (hidden at the end of the current message).
Signed-off-by: Angus Salkeld asalkeld@redhat.com --- lib/ipc_us.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-)
diff --git a/lib/ipc_us.c b/lib/ipc_us.c index 579fa90..15c731f 100644 --- a/lib/ipc_us.c +++ b/lib/ipc_us.c @@ -242,7 +242,8 @@ qb_ipc_us_recv(struct qb_ipc_one_way * one_way, struct ipc_us_control *ctl = NULL;
retry_recv: - result = recv(one_way->u.us.sock, &data[processed], to_recv, MSG_NOSIGNAL | MSG_WAITALL); + result = recv(one_way->u.us.sock, &data[processed], to_recv, + MSG_NOSIGNAL | MSG_WAITALL); if (timeout == -1) { if (result == -1 && errno == EAGAIN) { goto retry_recv; @@ -272,35 +273,52 @@ retry_recv:
/* * recv a message of unknow size. - * (could use MSG_PEEK here) */ static ssize_t qb_ipc_us_recv_at_most(struct qb_ipc_one_way * one_way, void *msg, size_t len, int32_t timeout) { int32_t result; + int32_t processed = 0; + int32_t to_recv = sizeof(struct qb_ipc_request_header); + char *data = msg; struct ipc_us_control *ctl = NULL; + struct qb_ipc_request_header *hdr = NULL;
retry_recv: - result = recv(one_way->u.us.sock, msg, len, MSG_NOSIGNAL | MSG_WAITALL); + result = recv(one_way->u.us.sock, &data[processed], to_recv, + MSG_NOSIGNAL | MSG_WAITALL); if (timeout == -1) { if (result == -1 && errno == EAGAIN) { goto retry_recv; } } if (result == 0) { - qb_util_log(LOG_DEBUG, "recv(fd %d) got 0 bytes assuming ENOTCONN", + qb_util_log(LOG_DEBUG, + "recv(fd %d) got 0 bytes assuming ENOTCONN", one_way->u.us.sock); return -ENOTCONN; } if (result == -1) { return -errno; } + processed += result; + if (processed >= sizeof(struct qb_ipc_request_header) && hdr == NULL) { + hdr = (struct qb_ipc_request_header*)msg; + } + if (hdr) { + to_recv = hdr->size - processed; + } else { + to_recv = len - processed; + } + if (to_recv > 0) { + goto retry_recv; + } ctl = (struct ipc_us_control *)one_way->u.us.shared_data; if (ctl) { (void)qb_atomic_int_dec_and_test(&ctl->sent); } - return result; + return processed; }