sys_close guarantees that it has closed the file descriptor when it returns, even if it returns EINTR. Thus, repeating a call to close(2) when it returns EINTR is always a mistake on NetBSD, and on other systems as well such as FreeBSD and Linux. (This conforms to POSIX, as would an implementation of close(2) that leaves the file descriptor open on EINTR.) It is a particularly nasty mistake in multithreaded programs because by it, one thread can inadvertently close a file descriptor that another thread just opened.
That leaves me wondering: Can sys_close ever return ERESTART? I started trying to follow the twisty maze of passages all alike through file systems including nfs and smbfs, and I am not yet sure whether I have found a code path yielding ERESTART. However, the difficulty of proving whether or not it can return ERESTART suggests to me that perhaps we ought to have a guard against it in sys_close: Index: sys_descrip.c =================================================================== RCS file: /cvsroot/src/sys/kern/sys_descrip.c,v retrieving revision 1.23 diff -p -u -r1.23 sys_descrip.c --- sys_descrip.c 31 Oct 2011 21:31:29 -0000 1.23 +++ sys_descrip.c 26 Dec 2011 04:59:40 -0000 @@ -467,11 +467,17 @@ sys_close(struct lwp *l, const struct sy /* { syscallarg(int) fd; } */ + int error; if (fd_getfile(SCARG(uap, fd)) == NULL) { return EBADF; } - return fd_close(SCARG(uap, fd)); + + error = fd_close(SCARG(uap, fd)); + if (error == ERESTART) + error = EINTR; + + return error; } /*