From 242ef4e8145eb20bac1e3d4554a1c2d627889dae Mon Sep 17 00:00:00 2001 From: Matthew Dillon Date: Sat, 19 May 2018 22:58:58 -0700 Subject: [PATCH] kernel - Change closefrom() EINTR behavior * closefrom() no longer breaks out of its loop if it gets an EINTR from a close(). EINTR can only occur from NFS in this situation, and the descriptor is still closed. Any EINTR's which occur will be rolled up and returned after the loop completes. * Callers usually ignore closefrom()'s return value anyway. Suggested-by: mjg --- sys/kern/kern_descrip.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c index c61c0b5540..fe16bc7b34 100644 --- a/sys/kern/kern_descrip.c +++ b/sys/kern/kern_descrip.c @@ -1316,6 +1316,8 @@ kern_closefrom(int fd) struct thread *td = curthread; struct proc *p = td->td_proc; struct filedesc *fdp; + int error; + int e2; KKASSERT(p); fdp = p->p_fd; @@ -1325,22 +1327,29 @@ kern_closefrom(int fd) /* * NOTE: This function will skip unassociated descriptors and - * reserved descriptors that have not yet been assigned. - * fd_lastfile can change as a side effect of kern_close(). + * reserved descriptors that have not yet been assigned. + * fd_lastfile can change as a side effect of kern_close(). + * + * NOTE: We accumulate EINTR errors and return EINTR if any + * close() returned EINTR. However, the descriptor is + * still closed and we do not break out of the loop. */ + error = 0; spin_lock(&fdp->fd_spin); while (fd <= fdp->fd_lastfile) { if (fdp->fd_files[fd].fp != NULL) { spin_unlock(&fdp->fd_spin); /* ok if this races another close */ - if (kern_close(fd) == EINTR) - return (EINTR); + e2 = kern_close(fd); + if (e2 == EINTR) + error = EINTR; spin_lock(&fdp->fd_spin); } ++fd; } spin_unlock(&fdp->fd_spin); - return (0); + + return error; } /* -- 2.11.4.GIT