Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 4 Apr 2014 12:31:13 +0000 (UTC)
From:      David Xu <davidxu@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r264114 - head/sys/kern
Message-ID:  <201404041231.s34CVD2Y078019@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: davidxu
Date: Fri Apr  4 12:31:13 2014
New Revision: 264114
URL: http://svnweb.freebsd.org/changeset/base/264114

Log:
  Fix SIGIO delivery. Use fsetown() to handle file descriptor owner
  ioctl and use pgsigio() to send SIGIO.
  
  Submitted by:	truckman
  Reviewed by:	mjg

Modified:
  head/sys/kern/subr_bus.c

Modified: head/sys/kern/subr_bus.c
==============================================================================
--- head/sys/kern/subr_bus.c	Fri Apr  4 11:19:02 2014	(r264113)
+++ head/sys/kern/subr_bus.c	Fri Apr  4 12:31:13 2014	(r264114)
@@ -391,11 +391,12 @@ static struct dev_softc
 	int	inuse;
 	int	nonblock;
 	int	queued;
+	int	async;
 	struct mtx mtx;
 	struct cv cv;
 	struct selinfo sel;
 	struct devq devq;
-	struct proc *async_proc;
+	struct sigio *sigio;
 } devsoftc;
 
 static struct cdev *devctl_dev;
@@ -422,7 +423,7 @@ devopen(struct cdev *dev, int oflags, in
 	/* move to init */
 	devsoftc.inuse = 1;
 	devsoftc.nonblock = 0;
-	devsoftc.async_proc = NULL;
+	devsoftc.async = 0;
 	mtx_unlock(&devsoftc.mtx);
 	return (0);
 }
@@ -433,8 +434,8 @@ devclose(struct cdev *dev, int fflag, in
 
 	mtx_lock(&devsoftc.mtx);
 	devsoftc.inuse = 0;
-	devsoftc.async_proc = NULL;
 	cv_broadcast(&devsoftc.cv);
+	funsetown(&devsoftc.sigio);
 	mtx_unlock(&devsoftc.mtx);
 	return (0);
 }
@@ -490,33 +491,21 @@ devioctl(struct cdev *dev, u_long cmd, c
 			devsoftc.nonblock = 0;
 		return (0);
 	case FIOASYNC:
-		/*
-		 * FIXME:
-		 * Since this is a simple assignment there is no guarantee that
-		 * devsoftc.async_proc consumers will get a valid pointer.
-		 *
-		 * Example scenario where things break (processes A and B):
-		 * 1. A opens devctl
-		 * 2. A sends fd to B
-		 * 3. B sets itself as async_proc
-		 * 4. B exits
-		 *
-		 * However, normally this requires root privileges and the only
-		 * in-tree consumer does not behave in a dangerous way so the
-		 * issue is not critical.
-		 */
 		if (*(int*)data)
-			devsoftc.async_proc = td->td_proc;
+			devsoftc.async = 1;
 		else
-			devsoftc.async_proc = NULL;
+			devsoftc.async = 0;
+		return (0);
+	case FIOSETOWN:
+		return fsetown(*(int *)data, &devsoftc.sigio);
+	case FIOGETOWN:
+		*(int *)data = fgetown(&devsoftc.sigio);
 		return (0);
 
 		/* (un)Support for other fcntl() calls. */
 	case FIOCLEX:
 	case FIONCLEX:
 	case FIONREAD:
-	case FIOSETOWN:
-	case FIOGETOWN:
 	default:
 		break;
 	}
@@ -560,7 +549,6 @@ void
 devctl_queue_data_f(char *data, int flags)
 {
 	struct dev_event_info *n1 = NULL, *n2 = NULL;
-	struct proc *p;
 
 	if (strlen(data) == 0)
 		goto out;
@@ -590,13 +578,8 @@ devctl_queue_data_f(char *data, int flag
 	cv_broadcast(&devsoftc.cv);
 	mtx_unlock(&devsoftc.mtx);
 	selwakeup(&devsoftc.sel);
-	/* XXX see a comment in devioctl */
-	p = devsoftc.async_proc;
-	if (p != NULL) {
-		PROC_LOCK(p);
-		kern_psignal(p, SIGIO);
-		PROC_UNLOCK(p);
-	}
+	if (devsoftc.async && devsoftc.sigio != NULL)
+		pgsigio(&devsoftc.sigio, SIGIO, 0);
 	return;
 out:
 	/*



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