tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

close and ERESTART



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;
 }
 
 /*


Home | Main Index | Thread Index | Old Index