manoj 99/10/12 13:37:05
Modified: src/main http_protocol.c Log: Attempt to make ap_send_fb work again. This is untested, but it works better than the old version because it compiles. Revision Changes Path 1.20 +28 -71 apache-2.0/src/main/http_protocol.c Index: http_protocol.c =================================================================== RCS file: /home/cvs/apache-2.0/src/main/http_protocol.c,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -u -r1.19 -r1.20 --- http_protocol.c 1999/10/11 22:07:25 1.19 +++ http_protocol.c 1999/10/12 20:36:56 1.20 @@ -2056,9 +2056,6 @@ return total_bytes_sent; } - -/* TODO: reimplement ap_send_fb */ -#if 0 /* * Send the body of a response to the client. */ @@ -2071,82 +2068,46 @@ { char buf[IOBUFSIZE]; long total_bytes_sent = 0; - register int n, w, o, len, fd; - struct pollfd fds; + long zero_timeout = 0; + int n, w, rc, o; - if (length == 0) + if (length == 0) { return 0; - - /* Make fb unbuffered and non-blocking */ - ap_bsetflag(fb, B_RD, 0); - fd = ap_bfileno(fb, B_RD); - ap_bnonblock(fd); -#ifdef CHECK_FD_SETSIZE - if (fd >= FD_SETSIZE) { - ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, NULL, - "send body: filedescriptor (%u) larger than FD_SETSIZE (%u) " - "found, you probably need to rebuild Apache with a " - "larger FD_SETSIZE", fd, FD_SETSIZE); - return 0; } -#endif - fds.fd = fd; - fds.events = POLLIN; + /* This function tries to as much as possible through non-blocking + * reads so that it can do writes while waiting for the CGI to + * produce more data. This way, the CGI's output gets to the client + * as soon as possible */ + ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout); while (!ap_is_aborted(r->connection)) { -#ifdef NDELAY_PIPE_RETURNS_ZERO - /* Contributed by [EMAIL PROTECTED] for UTS 2.1.2, where the fcntl */ - /* O_NDELAY flag causes read to return 0 when there's nothing */ - /* available when reading from a pipe. That makes it tricky */ - /* to detect end-of-file :-(. This stupid bug is even documented */ - /* in the read(2) man page where it says that everything but */ - /* pipes return -1 and EAGAIN. That makes it a feature, right? */ - int afterselect = 0; -#endif - if ((length > 0) && (total_bytes_sent + IOBUFSIZE) > length) - len = length - total_bytes_sent; - else - len = IOBUFSIZE; - - do { - n = ap_bread(fb, buf, len); -#ifdef NDELAY_PIPE_RETURNS_ZERO - if ((n > 0) || (n == 0 && afterselect)) - break; -#else - if (n >= 0) - break; -#endif - if (ap_is_aborted(r->connection)) + n = ap_bread(fb, buf, sizeof(buf)); + if (n <= 0) { + if (n == 0) { + (void) ap_rflush(r); break; - if (n < 0 && errno != EAGAIN /* ZZZ rethink for threaded impl */) + } + if (n == -1 && errno != EAGAIN) { + r->connection->aborted = 1; break; + } + /* next read will block, so flush the client now */ + rc = ap_bflush(r->connection->client); - /* we need to block, so flush the output first */ - if (ap_bflush(r->connection->client) < 0) { - ap_log_rerror(APLOG_MARK, APLOG_INFO, r, - "client stopped connection before send body completed"); - ap_bsetflag(r->connection->client, B_EOUT, 1); + ap_bsetopt(fb, BO_TIMEOUT, &r->server->timeout); + n = ap_bread(fb, buf, sizeof(buf)); + if (n <= 0) { + if (n == 0) { + (void) ap_rflush(r); + } r->connection->aborted = 1; break; } - /* - * we don't care what poll says, we might as well loop back - * around and try another read - */ - /* use AP funcs */ - poll(&fds, 1, -1); -#ifdef NDELAY_PIPE_RETURNS_ZERO - afterselect = 1; -#endif - } while (!ap_is_aborted(r->connection)); - - if (n < 1 || ap_is_aborted(r->connection)) { - break; + ap_bsetopt(fb, BO_TIMEOUT, &zero_timeout); } + o = 0; - while (n && !ap_is_aborted(r->connection)) { w = ap_bwrite(r->connection->client, &buf[o], n); if (w > 0) { @@ -2157,7 +2118,7 @@ else if (w < 0) { if (!ap_is_aborted(r->connection)) { ap_log_rerror(APLOG_MARK, APLOG_INFO, r, - "client stopped connection before send body completed"); + "client stopped connection before rflush completed"); ap_bsetflag(r->connection->client, B_EOUT, 1); r->connection->aborted = 1; } @@ -2165,14 +2126,10 @@ } } } - SET_BYTES_SENT(r); return total_bytes_sent; } -#endif - - /* The code writes MMAP_SEGMENT_SIZE bytes at a time. This is due to Apache's * timeout model, which is a timeout per-write rather than a time for the * entire transaction to complete. Essentially this should be small enough @@ -2378,7 +2335,7 @@ API_EXPORT(int) ap_rflush(request_rec *r) { if (ap_bflush(r->connection->client) < 0) { - if (!r->connection->aborted) { + if (!ap_is_aborted(r->connection)) { ap_log_rerror(APLOG_MARK, APLOG_INFO, r, "client stopped connection before rflush completed"); ap_bsetflag(r->connection->client, B_EOUT, 1);