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:
        /*
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to