- fpp = fdp->fd_ofiles;
- for (i = fdp->fd_lastfile; i-- >= 0; fpp++)
- if (*fpp)
- (void) closef(*fpp, p);
+ for (i = fdp->fd_lastfile; i >= 0; i--)
+#if 1 /* WORKAROUND */
+ /*
+ * Merlot: need to remove the bogus f_data check
+ * from the following "if" statement. It's there
+ * because of the network/kernel funnel race on a
+ * close of a socket vs. fdfree on exit. See
+ * Radar rdar://problem/3365650 for details, but
+ * the sort version is the commment before the "if"
+ * above is wrong under certain circumstances.
+ *
+ * We have to do this twice, in case knote_fdclose()
+ * results in a block.
+ *
+ * This works because an fdfree() will set all fields
+ * in the struct file to -1.
+ */
+ if ((fp = fdp->fd_ofiles[i]) != NULL &&
+ fp->f_data != (caddr_t)-1) {
+ if (i < fdp->fd_knlistsize)
+ knote_fdclose(p, i);
+ if (fp->f_data != (caddr_t)-1)
+ (void) closef(fp, p);
+ }
+#else /* !WORKAROUND */
+ if ((fp = fdp->fd_ofiles[i]) != NULL) {
+ if (i < fdp->fd_knlistsize)
+ knote_fdclose(p, i);
+ (void) closef(fp, p);
+ }
+#endif /* !WORKAROUND */