Date: Thu, 21 Feb 2008 09:54:14 -0600 (CST) From: Dan Nelson <dnelson@allantgroup.com> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/120948: sendfile(2) doesn't send trailers Message-ID: <200802211554.m1LFsEcb074499@dan.emsphone.com> Resent-Message-ID: <200802211600.m1LG05MK063213@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 120948 >Category: kern >Synopsis: sendfile(2) doesn't send trailers >Confidential: no >Severity: serious >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Thu Feb 21 16:00:05 UTC 2008 >Closed-Date: >Last-Modified: >Originator: Dan Nelson >Release: FreeBSD 7.0-PRERELEASE i386 >Organization: The Allant Group >Environment: System: FreeBSD dan.emsphone.com 7.0-PRERELEASE FreeBSD 7.0-PRERELEASE #534: Thu Feb 21 09:24:12 CST 2008 zsh@dan.emsphone.com:/usr/src-7/sys/i386/compile/DANSMP i386 >Description: rev 1.240 of uipc_syscalls.c converted the "send file" part of sendfile(2) from a counted for-loop to an infinite loop, but the code for breaking out of the loop jumps to the wrong place on success, and the code for sending the trailer is never called. >How-To-Repeat: Try the following program. Example of correct output: Should receive 48 bytes: rv=0, count=48 rv=48, data=<[this is header]FreeBSD 7.0-PRER[this is trailr]> #include <arpa/inet.h> #include <fcntl.h> #include <netinet/in.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/types.h> #include <sys/uio.h> #include <unistd.h> int main(void) { int socks[3]; int fd; unsigned int len; int rv; char buffer[8192]; off_t count = 0; struct sockaddr_in sin; struct iovec h, t; struct sf_hdtr hdtr; printf("Should receive 48 bytes:\n"); memset(socks, 0, sizeof(socks)); socks[0] = socket(PF_INET, SOCK_STREAM, 0); socks[1] = socket(PF_INET, SOCK_STREAM, 0); sin.sin_len = sizeof(sin); sin.sin_family = AF_INET; inet_aton("0.0.0.0", &sin.sin_addr); sin.sin_port = 0; bind(socks[0], &sin, sizeof(sin)); listen(socks[0], 16); len = sizeof(sin); getsockname(socks[0], &sin, &len); connect(socks[1], &sin, sizeof(sin)); socks[2] = accept(socks[0], NULL, 0); /* send 3 16-byte chunks: header, file, trailer */ h.iov_base = "[this is header]"; h.iov_len = strlen(h.iov_base); t.iov_base = "[this is trailr]"; t.iov_len = strlen(t.iov_base); hdtr.headers = &h; hdtr.hdr_cnt = 1; hdtr.trailers = &t; hdtr.trl_cnt = 1; fd = open("/etc/motd", O_RDONLY); rv = sendfile(fd, socks[1], 0, 16, &hdtr, &count, 0); printf("rv=%d, count=%lld\n", rv, count); sleep(1); memset(buffer, 0, 8192); rv = read(socks[2], &buffer, 8192); printf("rv=%d, data=<%s>\n", rv, buffer); return 0; } >Fix: This works for me: Index: uipc_syscalls.c =================================================================== RCS file: /home/ncvs/src/sys/kern/uipc_syscalls.c,v retrieving revision 1.259.2.2 diff -u -r1.259.2.2 uipc_syscalls.c --- uipc_syscalls.c 14 Feb 2008 11:44:59 -0000 1.259.2.2 +++ uipc_syscalls.c 21 Feb 2008 15:11:24 -0000 @@ -2172,7 +2172,9 @@ } /* Quit outer loop on error or when we're done. */ - if (error || done) + if (done) + break; + if (error) goto done; } >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200802211554.m1LFsEcb074499>