From nobody@FreeBSD.org  Tue Sep  1 21:56:46 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 6AFF1106568B
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  1 Sep 2009 21:56:46 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 59E248FC1A
	for <freebsd-gnats-submit@FreeBSD.org>; Tue,  1 Sep 2009 21:56:46 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id n81LukJI009791
	for <freebsd-gnats-submit@FreeBSD.org>; Tue, 1 Sep 2009 21:56:46 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id n81Luk5Z009790;
	Tue, 1 Sep 2009 21:56:46 GMT
	(envelope-from nobody)
Message-Id: <200909012156.n81Luk5Z009790@www.freebsd.org>
Date: Tue, 1 Sep 2009 21:56:46 GMT
From: Bruce Cran <bruce@cran.org.uk>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] add data verification to tools/regression/sockets/sendfile
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         138465
>Category:       kern
>Synopsis:       [tools] [patch] add data verification to tools/regression/sockets/sendfile
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Tue Sep 01 22:00:11 UTC 2009
>Closed-Date:    Sun Feb 28 14:05:20 UTC 2010
>Last-Modified:  Sun Feb 28 14:05:20 UTC 2010
>Originator:     Bruce Cran
>Release:        8.0-BETA3
>Organization:
>Environment:
FreeBSD gluon.draftnet 8.0-BETA3 FreeBSD 8.0-BETA3 #1: Mon Aug 31 08:45:18 BST 2009     brucec@gluon.draftnet:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
Data corruption is known to occur when a file stored in a tmpfs filesystem is transferred using sendfile(2). The attached patch adds a step to verify that the data hasn't been corrupted by adding an MD5 checksum field to the header in tools/regression/sockets/sendfile.
>How-To-Repeat:

>Fix:


Patch attached with submission follows:

diff -r -U3 sendfile.orig/Makefile sendfile/Makefile
--- sendfile.orig/Makefile	2009-08-03 09:13:06.000000000 +0100
+++ sendfile/Makefile	2009-09-01 20:37:37.000000000 +0100
@@ -5,5 +5,6 @@
 PROG=	sendfile
 NO_MAN=
 WARNS?=	6
+LDADD = -lmd
 
 .include <bsd.prog.mk>
diff -r -U3 sendfile.orig/sendfile.c sendfile/sendfile.c
--- sendfile.orig/sendfile.c	2009-08-03 09:13:06.000000000 +0100
+++ sendfile/sendfile.c	2009-09-01 22:50:05.000000000 +0100
@@ -34,6 +34,7 @@
 
 #include <err.h>
 #include <limits.h>
+#include <md5.h>
 #include <signal.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -57,11 +58,15 @@
 	u_int32_t	th_header_length;
 	u_int32_t	th_offset;
 	u_int32_t	th_length;
+	char		th_md5[33];
 };
 
 pid_t	child_pid, parent_pid;
 int	listen_socket;
 int	file_fd;
+char	path[PATH_MAX];
+
+void cleanup(void);
 
 static int
 test_th(struct test_header *th, u_int32_t *header_length, u_int32_t *offset,
@@ -105,7 +110,9 @@
 	u_int32_t header_length, offset, length, counter;
 	struct test_header th;
 	ssize_t len;
-	char ch;
+	char buf[10240];
+	MD5_CTX md5ctx;
+	char *rxmd5;
 
 	len = read(accept_socket, &th, sizeof(th));
 	if (len < 0)
@@ -116,19 +123,30 @@
 	if (test_th(&th, &header_length, &offset, &length) == 0)
 		errx(1, "test_th: bad");
 
+	MD5Init(&md5ctx);
+
 	counter = 0;
 	while (1) {
-		len = read(accept_socket, &ch, sizeof(ch));
+		len = read(accept_socket, buf, sizeof(buf));
 		if (len < 0)
 			err(1, "read");
 		if (len == 0)
 			break;
-		counter++;
-		/* XXXRW: Validate byte here. */
+		counter += len;
+		MD5Update(&md5ctx, buf, len);
 	}
+
 	if (counter != header_length + length)
 		errx(1, "receive_test: expected (%d, %d) received %d",
 		    header_length, length, counter);
+
+	rxmd5 = MD5End(&md5ctx, NULL);
+	
+	if (memcmp(th.th_md5, rxmd5, 33) != 0)
+		err(1, "receive_test: expected %s, received %s",
+		    th.th_md5, rxmd5);
+
+	free(rxmd5);
 }
 
 static void
@@ -171,12 +189,13 @@
 init_th(struct test_header *th, u_int32_t header_length, u_int32_t offset,
     u_int32_t length)
 {
-
 	bzero(th, sizeof(*th));
 	th->th_magic = htonl(TEST_MAGIC);
 	th->th_header_length = htonl(header_length);
 	th->th_offset = htonl(offset);
 	th->th_length = htonl(length);
+
+	MD5FileChunk(path, th->th_md5, offset, length);
 }
 
 static void
@@ -196,6 +215,14 @@
 	if (len != 0)
 		errx(1, "lseek: %zd", len);
 
+	if (length == 0)
+	{
+		struct stat st;
+		if (fstat(file_fd, &st) < 0)
+			err(1, "fstat");
+		length = st.st_size - offset;
+	}
+
 	init_th(&th, header_length, offset, length);
 
 	len = write(connect_socket, &th, sizeof(th));
@@ -311,14 +338,23 @@
 	(void)kill(child_pid, SIGKILL);
 }
 
+void
+cleanup(void)
+{
+	if (*path != '\0')
+		unlink(path);
+}
+
 int
 main(void)
 {
-	char path[PATH_MAX], *page_buffer;
+	char *page_buffer;
 	struct sockaddr_in sin;
 	int pagesize;
 	ssize_t len;
 
+	*path = '\0';
+
 	pagesize = getpagesize();
 	page_buffer = malloc(TEST_PAGES * pagesize);
 	if (page_buffer == NULL)
@@ -337,7 +373,7 @@
 
 	snprintf(path, PATH_MAX, "/tmp/sendfile.XXXXXXXXXXXX");
 	file_fd = mkstemp(path);
-	(void)unlink(path);
+	atexit(cleanup);
 
 	len = write(file_fd, page_buffer, TEST_PAGES * pagesize);
 	if (len < 0)


>Release-Note:
>Audit-Trail:

From: Bruce Cran <bruce@cran.org.uk>
To: bug-followup@FreeBSD.org, bruce@cran.org.uk
Subject: Re: kern/138465: [tools] [patch] add data verification to tools/regression/sockets/sendfile
Date: Mon, 28 Sep 2009 02:01:20 +0100
 
 Attached is an updated patch which converts the sendfile test to output
 results in the TAP format and allow subsequent tests to run if one
 fails.
 
 diff -r -U3 sendfile.orig/Makefile sendfile/Makefile
 --- sendfile.orig/Makefile	2009-09-28 02:48:19.000000000 +0100
 +++ sendfile/Makefile	2009-09-28 02:03:29.000000000 +0100
 @@ -5,5 +5,6 @@
  PROG=	sendfile
  NO_MAN=
  WARNS?=	6
 +LDADD = -lmd -pthread
  
  .include <bsd.prog.mk>
 diff -r -U3 sendfile.orig/sendfile.c sendfile/sendfile.c
 --- sendfile.orig/sendfile.c	2009-09-28 02:48:19.000000000 +0100
 +++ sendfile/sendfile.c	2009-09-28 02:46:29.000000000 +0100
 @@ -33,7 +33,10 @@
  #include <netinet/in.h>
  
  #include <err.h>
 +#include <errno.h>
  #include <limits.h>
 +#include <md5.h>
 +#include <pthread.h>
  #include <signal.h>
  #include <stdint.h>
  #include <stdio.h>
 @@ -47,113 +50,187 @@
   * of cases and performing limited validation.
   */
  
 +#define FAIL(msg)	{printf("# %s\n", msg); \
 +			return (-1);}
 +
 +#define FAIL_ERR(msg)	{printf("# %s: %s\n", msg, strerror(errno)); \
 +			return (-1);}
 +
  #define	TEST_PORT	5678
  #define	TEST_MAGIC	0x4440f7bb
  #define	TEST_PAGES	4
  #define	TEST_SECONDS	30
  
  struct test_header {
 -	u_int32_t	th_magic;
 -	u_int32_t	th_header_length;
 -	u_int32_t	th_offset;
 -	u_int32_t	th_length;
 +	uint32_t	th_magic;
 +	uint32_t	th_header_length;
 +	uint32_t	th_offset;
 +	uint32_t	th_length;
 +	char		th_md5[33];
 +};
 +
 +struct sendfile_test {
 +	uint32_t	hdr_length;
 +	uint32_t	offset;
 +	uint32_t	length;
  };
  
 -pid_t	child_pid, parent_pid;
 -int	listen_socket;
  int	file_fd;
 +char	path[PATH_MAX];
 +int	thread_exitcode;
 +int	listen_socket;
 +int	accept_socket;
 +
 +void cleanup(void);
  
  static int
 -test_th(struct test_header *th, u_int32_t *header_length, u_int32_t *offset,
 -    u_int32_t *length)
 +test_th(struct test_header *th, uint32_t *header_length, uint32_t *offset,
 +    uint32_t *length)
  {
  
  	if (th->th_magic != htonl(TEST_MAGIC))
 -		return (0);
 +		FAIL("magic number not found in header")
  	*header_length = ntohl(th->th_header_length);
  	*offset = ntohl(th->th_offset);
  	*length = ntohl(th->th_length);
 -	return (1);
 +	return (0);
  }
  
  static void
  signal_alarm(int signum)
  {
 -
  	(void)signum;
 +
 +	printf("# test timeout\n");
 +	thread_exitcode = -1;
 +
 +	if (accept_socket > 0)
 +		close(accept_socket);
 +	if (listen_socket > 0)
 +		close(listen_socket);
 +
 +	pthread_exit(&thread_exitcode);
  }
  
  static void
  setup_alarm(int seconds)
  {
 +	struct itimerval itv;
 +	bzero(&itv, sizeof(itv));
 +	(void)seconds;
 +	itv.it_value.tv_sec = seconds;
  
  	signal(SIGALRM, signal_alarm);
 -	alarm(seconds);
 +	setitimer(ITIMER_REAL, &itv, NULL);
  }
  
  static void
  cancel_alarm(void)
  {
 -
 -	alarm(0);
 -	signal(SIGALRM, SIG_DFL);
 +	struct itimerval itv;
 +	bzero(&itv, sizeof(itv));
 +	setitimer(ITIMER_REAL, &itv, NULL);
  }
  
 -static void
 -receive_test(int accept_socket)
 +static int
 +receive_test(void)
  {
 -	u_int32_t header_length, offset, length, counter;
 +	uint32_t header_length, offset, length, counter;
  	struct test_header th;
  	ssize_t len;
 -	char ch;
 +	char buf[10240];
 +	MD5_CTX md5ctx;
 +	char *rxmd5;
  
  	len = read(accept_socket, &th, sizeof(th));
 -	if (len < 0)
 -		err(1, "read");
 -	if ((size_t)len < sizeof(th))
 -		errx(1, "read: %zd", len);
 +	if (len < 0 || (size_t)len < sizeof(th))
 +		FAIL_ERR("read")
 +
 +	if (test_th(&th, &header_length, &offset, &length) != 0)
 +		return (-1);
  
 -	if (test_th(&th, &header_length, &offset, &length) == 0)
 -		errx(1, "test_th: bad");
 +	MD5Init(&md5ctx);
  
  	counter = 0;
  	while (1) {
 -		len = read(accept_socket, &ch, sizeof(ch));
 -		if (len < 0)
 -			err(1, "read");
 -		if (len == 0)
 +		len = read(accept_socket, buf, sizeof(buf));
 +		if (len < 0 || len == 0)
  			break;
 -		counter++;
 -		/* XXXRW: Validate byte here. */
 +		counter += len;
 +		MD5Update(&md5ctx, buf, len);
  	}
 -	if (counter != header_length + length)
 -		errx(1, "receive_test: expected (%d, %d) received %d",
 -		    header_length, length, counter);
 +
 +	rxmd5 = MD5End(&md5ctx, NULL);
 +	
 +	if ((counter != header_length+length) || 
 +			memcmp(th.th_md5, rxmd5, 33) != 0)
 +		FAIL("receive length mismatch")
 +
 +	free(rxmd5);
 +	return (0);
  }
  
 -static void
 -run_child(void)
 +static void*
 +run_child(void* arg)
  {
 -	int accept_socket;
 +	struct sockaddr_in sin;
  
 -	while (1) {
 -		accept_socket = accept(listen_socket, NULL, NULL);	
 -		setup_alarm(TEST_SECONDS);
 -		receive_test(accept_socket);
 -		cancel_alarm();
 -		close(accept_socket);
 +	(void)arg;
 +
 +	listen_socket = socket(PF_INET, SOCK_STREAM, 0);
 +	if (listen_socket < 0) {
 +		printf("# socket: %s\n", strerror(errno));
 +		goto error;
 +	}
 +
 +	bzero(&sin, sizeof(sin));
 +	sin.sin_len = sizeof(sin);
 +	sin.sin_family = AF_INET;
 +	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 +	sin.sin_port = htons(TEST_PORT);
 +
 +	if (bind(listen_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
 +		printf("# bind: %s\n", strerror(errno));
 +		goto error;
  	}
 +	
 +	if (listen(listen_socket, -1) < 0) {
 +		printf("# listen: %s\n", strerror(errno));
 +		goto error;
 +	}
 +
 +	accept_socket = accept(listen_socket, NULL, NULL);	
 +	setup_alarm(TEST_SECONDS);
 +	if (receive_test() != 0)
 +		goto error;
 +
 +	thread_exitcode = 0;
 +	goto success;
 +
 +error:
 +	thread_exitcode = -1;
 +
 +success:
 +	cancel_alarm();
 +	if (accept_socket > 0)
 +		close(accept_socket);
 +	if (listen_socket > 0)
 +		close(listen_socket);
 +
 +	accept_socket = -1;
 +	listen_socket = -1;	
 +	pthread_exit(&thread_exitcode);
  }
  
  static int
 -new_test_socket(void)
 +new_test_socket(int *connect_socket)
  {
  	struct sockaddr_in sin;
 -	int connect_socket;
 +	int rc = 0;
  
 -	connect_socket = socket(PF_INET, SOCK_STREAM, 0);
 -	if (connect_socket < 0)
 -		err(1, "socket");
 +	*connect_socket = socket(PF_INET, SOCK_STREAM, 0);
 +	if (*connect_socket < 0)
 +		FAIL_ERR("socket")
  
  	bzero(&sin, sizeof(sin));
  	sin.sin_len = sizeof(sin);
 @@ -161,57 +238,65 @@
  	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
  	sin.sin_port = htons(TEST_PORT);
  
 -	if (connect(connect_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0)
 -		err(1, "connect");
 +	if (connect(*connect_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0)
 +		FAIL_ERR("connect")
  
 -	return (connect_socket);
 +	return (rc);
  }
  
  static void
 -init_th(struct test_header *th, u_int32_t header_length, u_int32_t offset,
 -    u_int32_t length)
 +init_th(struct test_header *th, uint32_t header_length, uint32_t offset,
 +    uint32_t length)
  {
 -
  	bzero(th, sizeof(*th));
  	th->th_magic = htonl(TEST_MAGIC);
  	th->th_header_length = htonl(header_length);
  	th->th_offset = htonl(offset);
  	th->th_length = htonl(length);
 +
 +	MD5FileChunk(path, th->th_md5, offset, length);
  }
  
 -static void
 -send_test(int connect_socket, u_int32_t header_length, u_int32_t offset,
 -    u_int32_t length)
 +static int
 +send_test(int connect_socket, struct sendfile_test test)
  {
  	struct test_header th;
  	struct sf_hdtr hdtr, *hdtrp;
  	struct iovec headers;
  	char *header;
  	ssize_t len;
 +	int length;
  	off_t off;
  
  	len = lseek(file_fd, 0, SEEK_SET);
 -	if (len < 0)
 -		err(1, "lseek");
  	if (len != 0)
 -		errx(1, "lseek: %zd", len);
 +		FAIL_ERR("lseek")
  
 -	init_th(&th, header_length, offset, length);
 +	if (test.length == 0)
 +	{
 +		struct stat st;
 +		if (fstat(file_fd, &st) < 0)
 +			FAIL_ERR("fstat")
 +		length = st.st_size - test.offset;
 +	}
 +	else
 +		length = test.length;
 +
 +	init_th(&th, test.hdr_length, test.offset, length);
  
  	len = write(connect_socket, &th, sizeof(th));
 -	if (len < 0)
 -		err(1, "send");
  	if (len != sizeof(th))
 -		err(1, "send: %zd", len);
 +		return (-1);
  
 -	if (header_length != 0) {
 -		header = malloc(header_length);
 +	if (test.hdr_length != 0) {
 +		header = malloc(test.hdr_length);
  		if (header == NULL)
 -			err(1, "malloc");
 +			FAIL_ERR("malloc")
 +
  		hdtrp = &hdtr;
  		bzero(&headers, sizeof(headers));
  		headers.iov_base = header;
 -		headers.iov_len = header_length;
 +		headers.iov_len = test.hdr_length;
  		bzero(&hdtr, sizeof(hdtr));
  		hdtr.headers = &headers;
  		hdtr.hdr_cnt = 1;
 @@ -222,148 +307,124 @@
  		header = NULL;
  	}
  
 -	if (sendfile(file_fd, connect_socket, offset, length, hdtrp, &off,
 -	    0) < 0)
 -		err(1, "sendfile");
 +	if (sendfile(file_fd, connect_socket, test.offset, test.length, 
 +				hdtrp, &off, 0) < 0) {
 +		if (header != NULL)
 +			free(header);
 +		FAIL_ERR("sendfile")
 +	}
  
  	if (length == 0) {
  		struct stat sb;
  
 -		if (fstat(file_fd, &sb) < 0)
 -			err(1, "fstat");
 -		length = sb.st_size - offset;
 -	}
 -
 -	if (off != length) {
 -		errx(1, "sendfile: off(%ju) != length(%ju)",
 -		    (uintmax_t)off, (uintmax_t)length);
 +		if (fstat(file_fd, &sb) == 0)
 +			length = sb.st_size - test.offset;
  	}
  
  	if (header != NULL)
  		free(header);
 +
 +	if (off != length)
 +		FAIL("offset != length")
 +
 +	return (0);
  }
  
  static void
  run_parent(void)
  {
  	int connect_socket;
 +	pthread_t rxthr;
 +	void *rxthr_exitcode;
 +	int test_num;
 +
 +	const int pagesize = getpagesize();
 +
 +	struct sendfile_test tests[10] = {
 +		{ .hdr_length = 0, .offset = 0, .length = 1 },
 +		{ .hdr_length = 0, .offset = 0, .length = pagesize },
 +		{ .hdr_length = 0, .offset = 1, .length = 1 },
 +		{ .hdr_length = 0, .offset = 1, .length = pagesize },
 +		{ .hdr_length = 0, .offset = pagesize, .length = pagesize },
 +		{ .hdr_length = 0, .offset = 0, .length = 2*pagesize },
 +		{ .hdr_length = 0, .offset = 0, .length = 0 },
 +		{ .hdr_length = 0, .offset = pagesize, .length = 0 },
 +		{ .hdr_length = 0, .offset = 2*pagesize, .length = 0 },
 +		{ .hdr_length = 0, .offset = TEST_PAGES*pagesize, .length = 0 }
 +	};
 +
 +	printf("1..10\n");
 +
 +	for (test_num = 1; test_num <= 10; test_num++) {
 +
 +		if (pthread_create(&rxthr, NULL, run_child, NULL) != 0) {
 +			printf("not ok %d\n", test_num);
 +			continue;
 +		}
 +
 +		sleep(1);
 +
 +		if (new_test_socket(&connect_socket) != 0) {
 +			printf("not ok %d\n", test_num);
 +			close(connect_socket);
 +			pthread_kill(rxthr, SIGALRM);
 +			continue;
 +		}
 +
 +		if (send_test(connect_socket, tests[test_num-1]) != 0) {
 +			printf("not ok %d\n", test_num);
 +			pthread_kill(rxthr, SIGALRM);
 +			close(connect_socket);
 +			continue;
 +		}
 +
 +		close(connect_socket);
 +		if (pthread_join(rxthr, &rxthr_exitcode) == 0) {
 +			int *exitcode = (int*)rxthr_exitcode;
 +			printf("%s %d\n", (*exitcode == 0)?
 +					"ok" : "not ok", test_num);
 +		}
 +		else
 +			printf("not ok %d\n", test_num);
 +	}
 +}
  
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 0, 1);
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 0, getpagesize());
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 1, 1);
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 1, getpagesize());
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, getpagesize(), getpagesize());
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 0, 2 * getpagesize());
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 0, 0);
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, getpagesize(), 0);
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, 2 * getpagesize(), 0);
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	connect_socket = new_test_socket();
 -	send_test(connect_socket, 0, TEST_PAGES * getpagesize(), 0);
 -	close(connect_socket);
 -
 -	sleep(1);
 -
 -	(void)kill(child_pid, SIGKILL);
 +void
 +cleanup(void)
 +{
 +	if (*path != '\0')
 +		unlink(path);
  }
  
  int
  main(void)
  {
 -	char path[PATH_MAX], *page_buffer;
 -	struct sockaddr_in sin;
 +	char *page_buffer;
  	int pagesize;
  	ssize_t len;
  
 +	*path = '\0';
 +
  	pagesize = getpagesize();
  	page_buffer = malloc(TEST_PAGES * pagesize);
  	if (page_buffer == NULL)
 -		err(1, "malloc");
 +		FAIL_ERR("malloc")
  	bzero(page_buffer, TEST_PAGES * pagesize);
  
 -	listen_socket = socket(PF_INET, SOCK_STREAM, 0);
 -	if (listen_socket < 0)
 -		err(1, "socket");
 -
 -	bzero(&sin, sizeof(sin));
 -	sin.sin_len = sizeof(sin);
 -	sin.sin_family = AF_INET;
 -	sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
 -	sin.sin_port = htons(TEST_PORT);
 -
  	snprintf(path, PATH_MAX, "/tmp/sendfile.XXXXXXXXXXXX");
  	file_fd = mkstemp(path);
 -	(void)unlink(path);
 +	atexit(cleanup);
  
  	len = write(file_fd, page_buffer, TEST_PAGES * pagesize);
  	if (len < 0)
 -		err(1, "write");
 +		FAIL_ERR("write")
  
  	len = lseek(file_fd, 0, SEEK_SET);
  	if (len < 0)
 -		err(1, "lseek");
 +		FAIL_ERR("lseek")
  	if (len != 0)
 -		errx(1, "lseek: %zd", len);
 -
 -	if (bind(listen_socket, (struct sockaddr *)&sin, sizeof(sin)) < 0)
 -		err(1, "bind");
 -
 -	if (listen(listen_socket, -1) < 0)
 -		err(1, "listen");
 -
 -	parent_pid = getpid();
 -	child_pid = fork();
 -	if (child_pid < 0)
 -		err(1, "fork");
 -	if (child_pid == 0) {
 -		child_pid = getpid();
 -		run_child();
 -	} else
 -		run_parent();
 +		FAIL("len != 0")
  
 +	run_parent();
  	return (0);
  }
 
 
 # This is a shell archive.  Save it in a file, remove anything before
 # this line, and then unpack it by entering "sh file".  Note, it may
 # create directories; files and directories will be owned by you and
 # have default permissions.
 #
 # This archive contains:
 #
 #	sendfile.t
 #
 echo x - sendfile.t
 sed 's/^X//' >sendfile.t << 'b6d1360dd5883d0daea12ff60ad5ff0a'
 X#!/bin/sh
 X
 Xcd `dirname $0`
 X
 Xexecutable=`basename $0 .t`
 X
 Xmake $executable 2>&1 > /dev/null
 X
 Xexec ./$executable
 b6d1360dd5883d0daea12ff60ad5ff0a
 exit
 
State-Changed-From-To: open->closed  
State-Changed-By: brucec 
State-Changed-When: Sun Feb 28 14:04:28 UTC 2010 
State-Changed-Why:  
A similar patch using fork() has been committed to HEAD. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=138465 
>Unformatted:
