Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 20 Sep 2015 21:18:34 +0000 (UTC)
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r288044 - head/sys/fs/fifofs
Message-ID:  <201509202118.t8KLIYxJ009834@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kib
Date: Sun Sep 20 21:18:33 2015
New Revision: 288044
URL: https://svnweb.freebsd.org/changeset/base/288044

Log:
  Ensure that when a blockable open of fifo returns success, a valid
  file descriptor opened for complimentary access exists as well.
  
  The implementation of the guarantee is done by counting the
  generations of readers and writers opens.  We return success and not
  EINTR or ERESTART error, when the sleep for complimentary opening is
  interrupted, but the generation was changed during the sleep.
  
  Longer explanation: assume there are two threads, A doing open("fifo",
  O_RDONLY) and B doing open("fifo", O_WRONLY), and no other threads
  either trying to open the fifo, nor there are any file descriptors
  referencing the fifo.  Before the change, it was possible e.g. for for
  thread A to return a valid file descriptor, while thread B returned
  EINTR if a signal to B was delivered simultaneously with the wakeup
  from A.  After the change, in this situation both A::open() and
  B::open() succeed and the signal is made "as if" it was noticed
  slightly later.  Note that the signal actual delivery is not changed,
  it is done by ast on syscall return path, so signal handler is still
  executed before first instruction after syscall.
  
  See PR for the code demonstrating the issue.
  
  PR:	203162
  Reported by:	Victor Stinner victor.stinner@gmail.com
  Reviewed by:	jilles
  Tested by:	bapt, pho
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Modified:
  head/sys/fs/fifofs/fifo_vnops.c

Modified: head/sys/fs/fifofs/fifo_vnops.c
==============================================================================
--- head/sys/fs/fifofs/fifo_vnops.c	Sun Sep 20 21:06:37 2015	(r288043)
+++ head/sys/fs/fifofs/fifo_vnops.c	Sun Sep 20 21:18:33 2015	(r288044)
@@ -64,6 +64,8 @@ struct fifoinfo {
 	struct pipe *fi_pipe;
 	long	fi_readers;
 	long	fi_writers;
+	u_int	fi_rgen;
+	u_int	fi_wgen;
 };
 
 static vop_print_t	fifo_print;
@@ -137,6 +139,7 @@ fifo_open(ap)
 	struct thread *td;
 	struct fifoinfo *fip;
 	struct pipe *fpipe;
+	u_int gen;
 	int error, stops_deferred;
 
 	vp = ap->a_vp;
@@ -164,6 +167,7 @@ fifo_open(ap)
 	PIPE_LOCK(fpipe);
 	if (ap->a_mode & FREAD) {
 		fip->fi_readers++;
+		fip->fi_rgen++;
 		if (fip->fi_readers == 1) {
 			fpipe->pipe_state &= ~PIPE_EOF;
 			if (fip->fi_writers > 0)
@@ -179,6 +183,7 @@ fifo_open(ap)
 			return (ENXIO);
 		}
 		fip->fi_writers++;
+		fip->fi_wgen++;
 		if (fip->fi_writers == 1) {
 			fpipe->pipe_state &= ~PIPE_EOF;
 			if (fip->fi_readers > 0)
@@ -187,6 +192,7 @@ fifo_open(ap)
 	}
 	if ((ap->a_mode & O_NONBLOCK) == 0) {
 		if ((ap->a_mode & FREAD) && fip->fi_writers == 0) {
+			gen = fip->fi_wgen;
 			VOP_UNLOCK(vp, 0);
 			stops_deferred = sigallowstop();
 			error = msleep(&fip->fi_readers, PIPE_MTX(fpipe),
@@ -194,7 +200,7 @@ fifo_open(ap)
 			if (stops_deferred)
 				sigdeferstop();
 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-			if (error) {
+			if (error != 0 && gen == fip->fi_wgen) {
 				fip->fi_readers--;
 				if (fip->fi_readers == 0) {
 					PIPE_LOCK(fpipe);
@@ -214,6 +220,7 @@ fifo_open(ap)
 			 */
 		}
 		if ((ap->a_mode & FWRITE) && fip->fi_readers == 0) {
+			gen = fip->fi_rgen;
 			VOP_UNLOCK(vp, 0);
 			stops_deferred = sigallowstop();
 			error = msleep(&fip->fi_writers, PIPE_MTX(fpipe),
@@ -221,7 +228,7 @@ fifo_open(ap)
 			if (stops_deferred)
 				sigdeferstop();
 			vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
-			if (error) {
+			if (error != 0 && gen == fip->fi_rgen) {
 				fip->fi_writers--;
 				if (fip->fi_writers == 0) {
 					PIPE_LOCK(fpipe);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201509202118.t8KLIYxJ009834>