aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/subr_bus.c
diff options
context:
space:
mode:
authorDavid Xu <davidxu@FreeBSD.org>2014-04-04 12:31:13 +0000
committerDavid Xu <davidxu@FreeBSD.org>2014-04-04 12:31:13 +0000
commit5055c92801a30a01d104d0dea5d52d54b3cdd834 (patch)
treedf082462df6a23b840bfc9fd351545fd60d56105 /sys/kern/subr_bus.c
parent605a34b065ade99e965300aab248f7a14c798d25 (diff)
downloadsrc-5055c92801a30a01d104d0dea5d52d54b3cdd834.tar.gz
src-5055c92801a30a01d104d0dea5d52d54b3cdd834.zip
Fix SIGIO delivery. Use fsetown() to handle file descriptor owner
ioctl and use pgsigio() to send SIGIO. Submitted by: truckman Reviewed by: mjg
Notes
Notes: svn path=/head/; revision=264114
Diffstat (limited to 'sys/kern/subr_bus.c')
-rw-r--r--sys/kern/subr_bus.c43
1 files changed, 13 insertions, 30 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c
index b5d4a168f2ff..f996b0608561 100644
--- a/sys/kern/subr_bus.c
+++ b/sys/kern/subr_bus.c
@@ -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, int devtype, struct thread *td)
/* 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, int devtype, struct thread *td)
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, caddr_t data, int fflag, struct thread *t
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 flags)
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:
/*