Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 29 Jul 2012 13:13:54 -0700
From:      Garrett Cooper <yanegomi@gmail.com>
To:        davidxu@freebsd.org
Cc:        freebsd-bugs@freebsd.org
Subject:   Re: kern/170203: [kern] piped dd&#39; s don&#39; t behave sanely when dealing with a fifo
Message-ID:  <CAGH67wR_Wq-iH6psNX69qEkL8YG1kQuTxQ-0s6PxW3bXwda4Vw@mail.gmail.com>
In-Reply-To: <5014A64A.3010106@gmail.com>
References:  <201207272150.q6RLo9ew012879@freefall.freebsd.org> <501482CD.6050708@gmail.com> <CAGH67wQYCf6N0hF4Hru63snCxVoPjBmLgjyPkVBRT7q7%2BgcqbQ@mail.gmail.com> <50148F42.20105@gmail.com> <5014A64A.3010106@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
On Sat, Jul 28, 2012 at 7:56 PM, David Xu <listlog2011@gmail.com> wrote:

...

> I have updated patch, the patch fixed lost-notification bug for select():
> http://people.freebsd.org/~davidxu/patch/fifopipe/kernel_pipe2.diff

    This patch prevents the hang from occurring on CURRENT / r238870
(it was missing a header definition in sys/pipe.h). Now all that
remains is chasing down why dd's records accounting is bogus.
    The attached patch makes the output somewhat more meaningful with
dd if it receives a SIGPIPE.
Thanks!
-Garrett

PS Fedora 17 does what I expect by reporting the actual number of
records transferred across the fifo.

[-- Attachment #2 --]
--- //depot/user/gcooper/atf-head/src/sys/fs/fifofs/fifo_vnops.c	2012-05-20 04:37:04.000000000 0000
+++ /scratch/p4/user/gcooper/atf-head/src/sys/fs/fifofs/fifo_vnops.c	2012-05-20 04:37:04.000000000 0000
--- /tmp/tmp.47847.94	2012-07-29 12:44:08.083384996 -0700
+++ /scratch/p4/user/gcooper/atf-head/src/sys/fs/fifofs/fifo_vnops.c	2012-07-29 12:00:03.501340141 -0700
@@ -283,8 +283,11 @@
 		if (fip->fi_readers == 0) {
 			PIPE_LOCK(cpipe);
 			cpipe->pipe_state |= PIPE_EOF;
-			if (cpipe->pipe_state & PIPE_WANTW)
+			if ((cpipe->pipe_state & PIPE_WANTW)) {
+				cpipe->pipe_state &= ~PIPE_WANTW;
 				wakeup(cpipe);
+			}
+			pipeselwakeup(cpipe);
 			PIPE_UNLOCK(cpipe);
 		}
 	}
@@ -293,10 +296,13 @@
 		if (fip->fi_writers == 0) {
 			PIPE_LOCK(cpipe);
 			cpipe->pipe_state |= PIPE_EOF;
-			if (cpipe->pipe_state & PIPE_WANTR)
+			if ((cpipe->pipe_state & PIPE_WANTR)) {
+				cpipe->pipe_state &= ~PIPE_WANTR;
 				wakeup(cpipe);
+			}
 			fip->fi_wgen++;
 			FIFO_UPDWGEN(fip, cpipe);
+			pipeselwakeup(cpipe);
 			PIPE_UNLOCK(cpipe);
 		}
 	}
--- //depot/user/gcooper/atf-head/src/sys/kern/sys_pipe.c	2012-05-20 04:37:04.000000000 0000
+++ /scratch/p4/user/gcooper/atf-head/src/sys/kern/sys_pipe.c	2012-05-20 04:37:04.000000000 0000
--- /tmp/tmp.47847.169	2012-07-29 12:44:08.157343208 -0700
+++ /scratch/p4/user/gcooper/atf-head/src/sys/kern/sys_pipe.c	2012-07-29 12:00:03.515338359 -0700
@@ -227,7 +227,6 @@
 static int pipe_paircreate(struct thread *td, struct pipepair **p_pp);
 static __inline int pipelock(struct pipe *cpipe, int catch);
 static __inline void pipeunlock(struct pipe *cpipe);
-static __inline void pipeselwakeup(struct pipe *cpipe);
 #ifndef PIPE_NODIRECT
 static int pipe_build_write_buffer(struct pipe *wpipe, struct uio *uio);
 static void pipe_destroy_write_buffer(struct pipe *wpipe);
@@ -607,7 +606,7 @@
 	}
 }
 
-static __inline void
+void
 pipeselwakeup(cpipe)
 	struct pipe *cpipe;
 {
@@ -738,7 +737,7 @@
 			rpipe->pipe_map.pos += size;
 			rpipe->pipe_map.cnt -= size;
 			if (rpipe->pipe_map.cnt == 0) {
-				rpipe->pipe_state &= ~PIPE_DIRECTW;
+				rpipe->pipe_state &= ~(PIPE_DIRECTW|PIPE_WANTW);
 				wakeup(rpipe);
 			}
 #endif
@@ -1001,6 +1000,7 @@
 			wakeup(wpipe);
 		}
 		pipeselwakeup(wpipe);
+		wpipe->pipe_state |= PIPE_WANTW;
 		pipeunlock(wpipe);
 		error = msleep(wpipe, PIPE_MTX(wpipe), PRIBIO | PCATCH,
 		    "pipdwt", 0);
--- //depot/user/gcooper/atf-head/src/sys/sys/pipe.h	2012-05-20 04:37:04.000000000 0000
+++ /scratch/p4/user/gcooper/atf-head/src/sys/sys/pipe.h	2012-05-20 04:37:04.000000000 0000
--- /tmp/tmp.47847.207	2012-07-29 12:44:08.176339128 -0700
+++ /scratch/p4/user/gcooper/atf-head/src/sys/sys/pipe.h	2012-07-29 12:17:53.592393892 -0700
@@ -143,5 +143,6 @@
 
 void	pipe_dtor(struct pipe *dpipe);
 int	pipe_named_ctor(struct pipe **ppipe, struct thread *td);
+void	pipeselwakeup(struct pipe *cpipe);
 
 #endif /* !_SYS_PIPE_H_ */

[-- Attachment #3 --]
--- //depot/user/gcooper/atf-head/src/bin/dd/dd.c	2012-05-20 04:37:04.000000000 0000
+++ /scratch/p4/user/gcooper/atf-head/src/bin/dd/dd.c	2012-05-20 04:37:04.000000000 0000
@@ -91,6 +91,7 @@
 
 	(void)signal(SIGINFO, summaryx);
 	(void)signal(SIGINT, terminate);
+	(void)signal(SIGPIPE, SIG_IGN);
 
 	atexit(summary);
 
@@ -116,6 +117,7 @@
 {
 	u_int cnt;
 	struct timeval tv;
+	struct stat sb;
 
 	if (in.name == NULL) {
 		in.name = "stdin";
@@ -138,7 +140,11 @@
 	} else {
 #define	OFLAGS \
     (O_CREAT | (ddflags & (C_SEEK | C_NOTRUNC) ? 0 : O_TRUNC))
-		out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
+
+		if (stat(out.name, &sb) != 0 || !S_ISFIFO(sb.st_mode))
+			out.fd = open(out.name, O_RDWR | OFLAGS, DEFFILEMODE);
+		else
+			out.fd = -1;
 		/*
 		 * May not have read access, so try again with write only.
 		 * Without read we may have a problem if output also does

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CAGH67wR_Wq-iH6psNX69qEkL8YG1kQuTxQ-0s6PxW3bXwda4Vw>