From: Bill Stoddard Date: Fri, 14 Apr 2000 17:38:14 +0000 (+0000) Subject: Allow for the possibility of receiving data regardless of the pipe X-Git-Tag: apache-doc-split-01~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3f836c5723666af1f57445adf336aa722e729d6e;p=thirdparty%2Fapache%2Fhttpd.git Allow for the possibility of receiving data regardless of the pipe error condition or receiving EOF on the pipe read. This patch assumes that a read returning APR_SUCCESS with 0 bytes read is equivalent to an EOF. Submitted by: Dean Gaudet Reviewed by: Bill Stoddard git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@84965 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/modules/http/http_protocol.c b/modules/http/http_protocol.c index fd1bd7e79c9..9608ddd3435 100644 --- a/modules/http/http_protocol.c +++ b/modules/http/http_protocol.c @@ -2152,7 +2152,9 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length) register int o; ap_ssize_t w; ap_ssize_t n; + ap_ssize_t bytes_read; ap_status_t rv; + ap_status_t read_rv; if (length == 0) { return 0; @@ -2165,33 +2167,10 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length) ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout); while (!ap_is_aborted(r->connection)) { - rv = ap_bread(fb, buf, sizeof(buf), &n); - if (n == 0) { - if (rv == APR_SUCCESS) { /* eof */ - (void) ap_rflush(r); - break; - } - if (rv != APR_EAGAIN) { - r->connection->aborted = 1; - break; - } - /* next read will block, so flush the client now */ - if (ap_rflush(r) == EOF) { - break; - } - - ap_bsetopt(fb, BO_TIMEOUT, &r->server->timeout); - rv = ap_bread(fb, buf, sizeof(buf), &n); - if (n == 0) { - if (rv == APR_SUCCESS) { /* eof */ - (void) ap_rflush(r); - } - r->connection->aborted = 1; - break; - } - ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout); - } - + read_rv = ap_bread(fb, buf, sizeof(buf), &n); + got_read: + bytes_read = n; + /* Regardless of read errors, EOF, etc, bytes may have been read */ o = 0; while (n && !ap_is_aborted(r->connection)) { rv = ap_bwrite(r->connection->client, &buf[o], n, &w); @@ -2203,13 +2182,42 @@ API_EXPORT(long) ap_send_fb_length(BUFF *fb, request_rec *r, long length) else if (rv != APR_SUCCESS) { if (!ap_is_aborted(r->connection)) { ap_log_rerror(APLOG_MARK, APLOG_INFO, rv, r, - "client stopped connection before rflush completed"); + "client stopped connection before rflush completed"); ap_bsetflag(r->connection->client, B_EOUT, 1); r->connection->aborted = 1; } break; } } + if (read_rv == APR_SUCCESS) { + /* Assume a sucessful read of 0 bytes is an EOF + * Note: I don't think this is ultimately the right thing. + * Read functions should explicitly return EOF. + * wgs + */ + if (bytes_read == 0) { + (void) ap_rflush(r); + break; + } + } + else if (read_rv == APR_EOF) { + (void) ap_rflush(r); + break; + } + else if (read_rv != APR_EAGAIN) { + r->connection->aborted = 1; + break; + } + else { + /* next read will block, so flush the client now */ + if (ap_rflush(r) == EOF) { + break; + } + ap_bsetopt(fb, BO_TIMEOUT, &r->server->timeout); + read_rv = ap_bread(fb, buf, sizeof(buf), &n); + ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout); + goto got_read; + } } SET_BYTES_SENT(r); return total_bytes_sent;