From 28378eb32161456dd347f5747598f5d33b25f239 Mon Sep 17 00:00:00 2001 From: Jeremy Allison Date: Tue, 15 Apr 2014 12:43:06 -0700 Subject: [PATCH] s3: smbd : default_sys_recvfile() and spice() recvfile were not written to cope with non-blocking sockets. When either the socket read() or splice() return -1 EWOULDBLOCK or EAGAIN, if no bytes have been processed yet return -1 and let the caller set blocking and retry. If bytes have been processed, just return them as a short read and let the caller retry with the remaining needed reads. Signed-off-by: Jeremy Allison --- source3/lib/recvfile.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/source3/lib/recvfile.c b/source3/lib/recvfile.c index 500a7e4..bffe07f 100644 --- a/source3/lib/recvfile.c +++ b/source3/lib/recvfile.c @@ -75,8 +75,33 @@ static ssize_t default_sys_recvfile(int fromfd, ssize_t read_ret; size_t toread = MIN(bufsize,count - total); - /* Read from socket - ignore EINTR. */ - read_ret = sys_read(fromfd, buffer, toread); + /* + * Read from socket - ignore EINTR. + * Can't use sys_read() as that also + * ignores EAGAIN and EWOULDBLOCK. + */ + do { + read_ret = read(fromfd, buffer, toread); + } while (read_ret == -1 && errno == EINTR); + +#if defined(EWOULDBLOCK) + if (read_ret == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) { +#else + if (read_ret == -1 && (errno == EAGAIN)) { +#endif + /* + * fromfd socket is in non-blocking mode. + * If we already read some and wrote + * it successfully, return that. + * Only return -1 if this is the first read + * attempt. Caller will handle both cases. + */ + if (total_written != 0) { + return total_written; + } + return -1; + } + if (read_ret <= 0) { /* EOF or socket error. */ return -1; @@ -184,6 +209,23 @@ ssize_t sys_recvfile(int fromfd, return default_sys_recvfile(fromfd, tofd, offset, count); } +#if defined(EWOULDBLOCK) + if (errno == EAGAIN || errno == EWOULDBLOCK) { +#else + if (errno == EAGAIN) { +#endif + /* + * fromfd socket is in non-blocking mode. + * If we already read some and wrote + * it successfully, return that. + * Only return -1 if this is the first read + * attempt. Caller will handle both cases. + */ + if (total_written != 0) { + return total_written; + } + return -1; + } break; } -- 1.9.1.423.g4596e3a