From: Vincent Bernat Date: Sat, 30 Mar 2013 14:42:51 +0000 (+0100) Subject: lib: fix sync_recv to handle segmentation X-Git-Tag: 0.7.2~19 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e581ec3043d528cadb56c5d49b1b29c92fa78d83;p=thirdparty%2Flldpd.git lib: fix sync_recv to handle segmentation While it should not happen with Unix sockets, a read() can return only partial data. Therefore, we continue to poll until we get the appropriate length. This fix was proposed by Chris Yang. Closes #31. --- diff --git a/src/lib/connection.c b/src/lib/connection.c index 3b3227cc..2fe7c44d 100644 --- a/src/lib/connection.c +++ b/src/lib/connection.c @@ -68,6 +68,7 @@ sync_recv(lldpctl_conn_t *lldpctl, { struct lldpctl_conn_sync_t *conn = user_data; size_t nb; + size_t remain, offset = 0; if (conn->fd == -1 && ((conn->fd = sync_connect(lldpctl)) == -1)) { @@ -75,14 +76,17 @@ sync_recv(lldpctl_conn_t *lldpctl, return LLDPCTL_ERR_CANNOT_CONNECT; } - while ((nb = read(conn->fd, (void*)data, length)) == -1) { - if (errno == EAGAIN || errno == EINTR) continue; - return LLDPCTL_ERR_CALLBACK_FAILURE; - } - return nb; + remain = length; + do { + if ((nb = read(conn->fd, (void*)data + offset, remain)) == -1 && + (errno == EAGAIN || errno == EINTR)) + continue; + remain -= nb; + offset += nb; + } while (remain > 0 && nb > 0); + return offset; } - lldpctl_conn_t* lldpctl_new(lldpctl_send_callback send, lldpctl_recv_callback recv, void *user_data) {