summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorIan Kent <raven@themaw.net>2018-11-08 13:26:57 -0500
committerSteve Dickson <steved@redhat.com>2018-11-08 13:28:50 -0500
commit3a17941dbbfcc8e9fcf08004992615a774443a0d (patch)
treecd08bea437802860111f682f0cbcf2c8a392f60c /src
parente80e668683f2e573c2aae7457b8efad8b4541f26 (diff)
downloadti-rpc-3a17941dbbfcc8e9fcf08004992615a774443a0d.tar.gz
Fix EOF detection on non-blocking socketlibtirpc-1-1-5-rc2
From: Ian Kent <raven@themaw.net> EOF on a non-blocking socket is incorrectly detected causing the socket to be closed if a client sends the RPC request in more than one write. This is becuase ->read_vc() returns 0 for a real EOF and for the error cases of EAGAIN or EWOULDBLOCK when there could be more data to come. The caller of ->read_vc() also fails to handle this case correctly returning XPRT_DIED in both cases. Also the stream context setting that indicates the request header has been reveived is not set after receiving the header which causes incorrect interpretation of the input for the case of a multiple read receive. Signed-off-by: Ian Kent <raven@themaw.net> Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/svc_vc.c7
-rw-r--r--src/xdr_rec.c18
2 files changed, 22 insertions, 3 deletions
diff --git a/src/svc_vc.c b/src/svc_vc.c
index 97a76a3..c23cd36 100644
--- a/src/svc_vc.c
+++ b/src/svc_vc.c
@@ -502,9 +502,14 @@ read_vc(xprtp, buf, len)
cfp = (struct cf_conn *)xprt->xp_p1;
if (cfp->nonblock) {
+ /* Since len == 0 is returned on zero length
+ * read or EOF errno needs to be reset before
+ * the read
+ */
+ errno = 0;
len = read(sock, buf, (size_t)len);
if (len < 0) {
- if (errno == EAGAIN)
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
len = 0;
else
goto fatal_err;
diff --git a/src/xdr_rec.c b/src/xdr_rec.c
index 7d535cf..676cc82 100644
--- a/src/xdr_rec.c
+++ b/src/xdr_rec.c
@@ -61,6 +61,7 @@
#include <rpc/svc.h>
#include <rpc/clnt.h>
#include <stddef.h>
+#include <errno.h>
#include "rpc_com.h"
static bool_t xdrrec_getlong(XDR *, long *);
static bool_t xdrrec_putlong(XDR *, const long *);
@@ -537,7 +538,13 @@ __xdrrec_getrec(xdrs, statp, expectdata)
n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp,
(int)sizeof (rstrm->in_header) - rstrm->in_hdrlen);
if (n == 0) {
- *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
+ /* EAGAIN or EWOULDBLOCK means a zero length
+ * read not an EOF.
+ */
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ *statp = XPRT_IDLE;
+ else
+ *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
return FALSE;
}
if (n < 0) {
@@ -564,6 +571,7 @@ __xdrrec_getrec(xdrs, statp, expectdata)
rstrm->in_header &= ~LAST_FRAG;
rstrm->last_frag = TRUE;
}
+ rstrm->in_haveheader = 1;
}
n = rstrm->readit(rstrm->tcp_handle,
@@ -576,7 +584,13 @@ __xdrrec_getrec(xdrs, statp, expectdata)
}
if (n == 0) {
- *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
+ /* EAGAIN or EWOULDBLOCK means a zero length
+ * read not an EOF.
+ */
+ if (errno == EAGAIN || errno == EWOULDBLOCK)
+ *statp = XPRT_IDLE;
+ else
+ *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
return FALSE;
}