From owner-freebsd-hackers Sat Dec 8 14:29: 0 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from elvis.mu.org (elvis.mu.org [216.33.66.196]) by hub.freebsd.org (Postfix) with ESMTP id D76D437B417; Sat, 8 Dec 2001 14:28:54 -0800 (PST) Received: by elvis.mu.org (Postfix, from userid 1192) id 6F54781E0D; Sat, 8 Dec 2001 16:28:49 -0600 (CST) Date: Sat, 8 Dec 2001 16:28:49 -0600 From: Alfred Perlstein To: hackers@freebsd.org Cc: dg@freebsd.org, jasone@freebsd.org Subject: sendfile libc_r fix. Message-ID: <20011208162849.H92148@elvis.mu.org> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG One of the apache guys recent got ahold of me with this bug in the libc_r code that wraps sendfile. Effectively what was happening was that the sf_hdr was only partially succeeding, however then the code would spew the contents of the file down the socket. There was also the problem that libc_r wasn't emulating the whacked out sendfile(2) semantics such that the amount of data in the headers is subtracted from the amount of data to be sent from the file. David, any chance you can fix this? I guess it's time to make use of that 'flags' argument? :) Here is a fix, it may have issues, but we're unsure of whether my fix is buggy or if apache is buggy at this point. Feedback would be appreciated. I'd like to commit this as an interm fix as it seems to make things better but not perfect. http://people.freebsd.org/~alfred/uthread_sf.diff Index: uthread_sendfile.c =================================================================== RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_sendfile.c,v retrieving revision 1.5 diff -u -r1.5 uthread_sendfile.c --- uthread_sendfile.c 10 Apr 2001 04:19:20 -0000 1.5 +++ uthread_sendfile.c 9 Dec 2001 00:00:32 -0000 @@ -48,13 +48,25 @@ ssize_t wvret, num = 0; off_t n, nwritten = 0; - /* Write the headers if any. */ + /* + * Write the headers if any. + * If some data is written but not all we must return here. + */ if ((hdtr != NULL) && (hdtr->headers != NULL)) { if ((wvret = writev(s, hdtr->headers, hdtr->hdr_cnt)) == -1) { ret = -1; goto ERROR; - } else + } else { + int i; + ssize_t hdrtot; + nwritten += wvret; + + for (i = 0, hdrtot = 0; i < hdtr->hdr_cnt; i++) + hdrtot += hdtr->headers[i].iov_len; + if (wvret < hdrtot) + goto SHORT_HEADER; + } } /* Lock the descriptors. */ @@ -87,7 +99,18 @@ /* Check if file operations are to block */ blocking = ((_thread_fd_table[s]->flags & O_NONBLOCK) == 0); - + + /* + * Emulate sendfile(2) weirdness, sendfile doesn't actually send + * nbytes of the file, it really sends (nbytes - headers_size) of + * the file. If (nbytes - headers_size) == 0 we just send trailers. + */ + if (nbytes != 0) { + nbytes -= nwritten; + if (nbytes <= 0) + goto ERROR_2; + } + /* * Loop while no error occurs and until the expected number of bytes are * written. @@ -144,6 +167,7 @@ nwritten += wvret; } } + SHORT_HEADER: if (sbytes != NULL) { /* * Number of bytes written in headers/trailers, plus in the main -- -Alfred Perlstein [alfred@freebsd.org] 'Instead of asking why a piece of software is using "1970s technology," start asking why software is ignoring 30 years of accumulated wisdom.' http://www.morons.org/rants/gpl-harmful.php3 To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message