]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/vfs/vfs_fsevents.c
xnu-792.25.20.tar.gz
[apple/xnu.git] / bsd / vfs / vfs_fsevents.c
index 3688244efe1c06ac46ee86a50b51cde3feed8515..801faa3c10644068d6f0af5c6273bc0c606b7fc0 100644 (file)
@@ -946,10 +946,13 @@ static int fsevents_installed = 0;
 static struct lock__bsd__ fsevents_lck;
 
 typedef struct fsevent_handle {
+    UInt32            flags;
+    SInt32            active;
     fs_event_watcher *watcher;
     struct selinfo    si;
 } fsevent_handle;
 
+#define FSEH_CLOSING   0x0001
 
 static int
 fseventsf_read(struct fileproc *fp, struct uio *uio,
@@ -981,15 +984,27 @@ fseventsf_ioctl(struct fileproc *fp, u_long cmd, caddr_t data, struct proc *p)
     pid_t pid = 0;
     fsevent_dev_filter_args *devfilt_args=(fsevent_dev_filter_args *)data;
 
+    OSAddAtomic(1, &fseh->active);
+    if (fseh->flags & FSEH_CLOSING) {
+       OSAddAtomic(-1, &fseh->active);
+       return 0;
+    }
+
     switch (cmd) {
        case FIONBIO:
        case FIOASYNC:
-           return 0;
+           ret = 0;
+           break;
 
        case FSEVENTS_DEVICE_FILTER: {
            int new_num_devices;
            dev_t *devices_to_watch, *tmp=NULL;
            
+           if (fseh->flags & FSEH_CLOSING) {
+               ret = 0;
+               break;
+           }
+
            if (devfilt_args->num_devices > 256) {
                ret = EINVAL;
                break;
@@ -1044,6 +1059,7 @@ fseventsf_ioctl(struct fileproc *fp, u_long cmd, caddr_t data, struct proc *p)
            break;
     }
 
+    OSAddAtomic(-1, &fseh->active);
     return (ret);
 }
 
@@ -1085,11 +1101,18 @@ static int
 fseventsf_close(struct fileglob *fg, struct proc *p)
 {
     fsevent_handle *fseh = (struct fsevent_handle *)fg->fg_data;
+    fs_event_watcher *watcher;
+    
+    OSBitOrAtomic(FSEH_CLOSING, &fseh->flags);
+    while (OSAddAtomic(0, &fseh->active) > 0) {
+       tsleep((caddr_t)fseh->watcher, PRIBIO, "fsevents-close", 1);
+    }
 
-    remove_watcher(fseh->watcher);
-
-    fg->fg_data = NULL;
+    watcher = fseh->watcher;
     fseh->watcher = NULL;
+    fg->fg_data = NULL;
+
+    remove_watcher(watcher);
     FREE(fseh, M_TEMP);
 
     return 0;
@@ -1228,7 +1251,7 @@ fseventsioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                proc_fdunlock(p);
            copyout((void *)&fd, CAST_USER_ADDR_T(fse_clone_args->fd), sizeof(int32_t));
                proc_fdlock(p);
-           *fdflags(p, fd) &= ~UF_RESERVED;
+               procfdtbl_releasefd(p, fd, NULL);
                fp_drop(p, fd, f, 1);
                proc_fdunlock(p);
            break;