]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/kern_event.c
xnu-1486.2.11.tar.gz
[apple/xnu.git] / bsd / kern / kern_event.c
index 92448a3f5b2e8b7bda0656221ed2b91ed74d9f71..1a0f609ca828a718151f96e7156ecaa605a85eb0 100644 (file)
@@ -1510,19 +1510,27 @@ kevent_register(struct kqueue *kq, struct kevent64_s *kev, __unused struct proc
 
                        error = fops->f_attach(kn);
 
-                       /*
-                        * Anyone trying to drop this knote will yield to
-                        * us, since KN_ATTACHING is set.
-                        */
                        kqlock(kq);
-                       if (error != 0 || (kn->kn_status & KN_DROPPING)) {
-                               if (error == 0) {
-                                       kn->kn_fop->f_detach(kn);
-                               }
+                       if (error != 0) {
+                               /*
+                                * Failed to attach correctly, so drop.
+                                * All other possible users/droppers
+                                * have deferred to us.
+                                */
                                kn->kn_status |= KN_DROPPING;
                                kqunlock(kq);
                                knote_drop(kn, p);
                                goto done;
+                       } else if (kn->kn_status & KN_DROPPING) {
+                               /*
+                                * Attach succeeded, but someone else
+                                * deferred their drop - now we have
+                                * to do it for them (after detaching).
+                                */
+                               kqunlock(kq);
+                               kn->kn_fop->f_detach(kn);
+                               knote_drop(kn, p);
+                               goto done;
                        }
                        kn->kn_status &= ~KN_ATTACHING;
                        kqunlock(kq);