Skip site navigation (1)Skip section navigation (2)
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>