Index: sys/kern/kern_descrip.c =================================================================== --- sys/kern/kern_descrip.c +++ sys/kern/kern_descrip.c @@ -1630,20 +1630,17 @@ atomic_store_rel_ptr((volatile void *)&fdp->fd_files, (uintptr_t)ntable); /* - * Do not free the old file table, as some threads may still - * reference entries within it. Instead, place it on a freelist - * which will be processed when the struct filedesc is released. + * Unless the current process has one thread and the file descriptor + * table has not been freed, do not free the old file table, as some + * threads may still reference entries within it. Instead, place + * it on a freelist which will be processed when the struct filedesc + * is released. * * Note that if onfiles == NDFILE, we're dealing with the original * static allocation contained within (struct filedesc0 *)fdp, * which must not be freed. */ - if (onfiles > NDFILE) { - ft = (struct freetable *)&otable->fdt_ofiles[onfiles]; - fdp0 = (struct filedesc0 *)fdp; - ft->ft_table = otable; - SLIST_INSERT_HEAD(&fdp0->fd_free, ft, ft_next); - } + /* * The map does not have the same possibility of threads still * holding references to it. So always free it as long as it @@ -1651,6 +1648,24 @@ */ if (NDSLOTS(onfiles) > NDSLOTS(NDFILE)) free(omap, M_FILEDESC); + + if (onfiles <= NDFILE) + /* Nothing remains to be freed */ + return; + + /* + * Now since onfiles > NDFILE, we free the table or add it to + * the free table list. + */ + if (((curproc->p_numthreads == 1) && (fdp->fd_refcnt == 1))\ + || (fdp->fd_lastfile == -1)) + free(otable, M_FILEDESC); + else { + ft = (struct freetable *)&otable->fdt_ofiles[onfiles]; + fdp0 = (struct filedesc0 *)fdp; + ft->ft_table = otable; + SLIST_INSERT_HEAD(&fdp0->fd_free, ft, ft_next); + } } /*