From 1bceb1d23783dbca5b62953d4a61a5b6e67f9133 Mon Sep 17 00:00:00 2001 From: Steven Dake Date: Wed, 17 Aug 2005 19:37:24 +0000 Subject: [PATCH] defect 501 this patch fixes short reads and writes between the library and executive git-svn-id: http://svn.fedorahosted.org/svn/corosync/trunk@797 fd59a12c-fef9-0310-b244-a6a79926bd2f --- lib/util.c | 144 ++++++++++++++++++++++++++++++++++++++++++++---- test/evsbench.c | 2 +- 2 files changed, 133 insertions(+), 13 deletions(-) diff --git a/lib/util.c b/lib/util.c index 56f0a219..dc9d9039 100644 --- a/lib/util.c +++ b/lib/util.c @@ -294,12 +294,10 @@ saSendRetry ( { SaErrorT error = SA_AIS_OK; int result; - struct msghdr msg_send; struct iovec iov_send; - - iov_send.iov_base = (void *)msg; - iov_send.iov_len = len; + char *rbuf = (char *)msg; + int processed = 0; msg_send.msg_iov = &iov_send; msg_send.msg_iovlen = 1; @@ -310,13 +308,61 @@ saSendRetry ( msg_send.msg_flags = 0; retry_send: + iov_send.iov_base = (void *)&rbuf[processed]; + iov_send.iov_len = len - processed; + result = sendmsg (s, &msg_send, flags); - if (result == -1 && errno == EINTR) { - goto retry_send; + + /* + * return immediately on any kind of syscall error that maps to + * SA_AIS_ERR if no part of message has been sent + */ + if (result == -1 && processed == 0) { + if (errno == EINTR) { + error = SA_AIS_ERR_TRY_AGAIN; + goto error_exit; + } + if (errno == EAGAIN) { + error = SA_AIS_ERR_TRY_AGAIN; + goto error_exit; + } + if (errno == EFAULT) { + error = SA_AIS_ERR_INVALID_PARAM; + goto error_exit; + } } + + /* + * retry read operations that are already started except + * for fault in that case, return ERR_LIBRARY + */ + if (result == -1 && processed > 0) { + if (errno == EINTR) { + goto retry_send; + } + if (errno == EAGAIN) { + goto retry_send; + } + if (errno == EFAULT) { + error = SA_AIS_ERR_LIBRARY; + goto error_exit; + } + } + + /* + * return ERR_LIBRARY on any other syscall error + */ if (result == -1) { error = SA_AIS_ERR_LIBRARY; + goto error_exit; } + + processed += result; + if (processed != len) { + goto retry_send; + } + +error_exit: return (error); } @@ -327,25 +373,99 @@ SaErrorT saSendMsgRetry ( { SaErrorT error = SA_AIS_OK; int result; + int total_size = 0; + int i; + int csize; + int csize_cntr; + int total_sent = 0; + int iov_len_sendmsg = iov_len; + struct iovec *iov_sendmsg = iov; + struct iovec iovec_save; + int iovec_saved_position = -1; struct msghdr msg_send; - msg_send.msg_iov = iov; - msg_send.msg_iovlen = iov_len; + for (i = 0; i < iov_len; i++) { + total_size += iov[i].iov_len; + } + msg_send.msg_iov = iov_sendmsg; + msg_send.msg_iovlen = iov_len_sendmsg; msg_send.msg_name = 0; msg_send.msg_namelen = 0; msg_send.msg_control = 0; msg_send.msg_controllen = 0; msg_send.msg_flags = 0; -retry_send: - result = sendmsg (s, &msg_send, MSG_NOSIGNAL); - if (result == -1 && errno == EINTR) { - goto retry_send; +retry_sendmsg: + result = sendmsg (s, &msg_send, MSG_NOSIGNAL | MSG_DONTWAIT); + /* + * Can't send now, and message not committed, so don't retry send + */ + if (result == -1 && iovec_saved_position == -1) { + if (errno == EINTR) { + error = SA_AIS_ERR_TRY_AGAIN; + goto error_exit; + } + if (errno == EAGAIN) { + error = SA_AIS_ERR_TRY_AGAIN; + goto error_exit; + } + if (errno == EFAULT) { + error = SA_AIS_ERR_INVALID_PARAM; + goto error_exit; + } } + + /* + * Retry (and block) if portion of message has already been written + */ + if (result == -1 && iovec_saved_position != -1) { + if (errno == EINTR) { + goto retry_sendmsg; + } + if (errno == EAGAIN) { + goto retry_sendmsg; + } + if (errno == EFAULT) { + error = SA_AIS_ERR_LIBRARY; + goto error_exit; + } + } + + /* + * ERR_LIBRARY for any other syscall error + */ if (result == -1) { error = SA_AIS_ERR_LIBRARY; + goto error_exit; } + + if (iovec_saved_position != -1) { + memcpy (&iov[iovec_saved_position], &iovec_save, sizeof (struct iovec)); + } + + total_sent += result; + if (total_sent != total_size) { + for (i = 0, csize = 0, csize_cntr = 0; i < iov_len; i++) { + csize += iov[i].iov_len; + if (csize > total_sent) { + break; + } + + csize_cntr += iov[i].iov_len; + } + memcpy (&iovec_save, &iov[i], sizeof (struct iovec)); + iovec_saved_position = i; + iov[i].iov_base = ((unsigned char *)(iov[i].iov_base)) + + (total_sent - csize_cntr); + iov[i].iov_len = total_size - total_sent; + msg_send.msg_iov = &iov[i]; + msg_send.msg_iovlen = iov_len - i; + + goto retry_sendmsg; + } + +error_exit: return (error); } diff --git a/test/evsbench.c b/test/evsbench.c index 243b85d8..e85f4f8a 100644 --- a/test/evsbench.c +++ b/test/evsbench.c @@ -167,7 +167,7 @@ int main (void) { result = evs_leave (handle, &groups[0], 1); printf ("Leave result %d\n", result); - size = 170000; + size = 1; for (i = 0; i < 225; i++) { /* number of repetitions - up to 50k */ evs_benchmark (handle, size);