From: email@example.com (Linus Torvalds)
Subject: Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs
Date: Wed, 17 Jul 2002 17:48:51 GMT
In article <20020717164933.GA2136@eskimo.com>,
Elladan <firstname.lastname@example.org> wrote:
>Consider what this says, if a particular OS doesn't pick a standard
>which the application can port to. It means that the *only way* to
>correctly close a file descriptor is like this:
> ret = close(fd);
>} while(ret == -1 && errno != EBADF);
The above is
(a) not portable
(b) not current practice
The "not portable" part comes from the fact that (as somebody pointed
out), a threaded environment in which the kernel _does_ close the FD on
errors, the FD may have been validly re-used (by the kernel) for some
other thread, and closing the FD a second time is a BUG.
The "not practice" comes from the fact that applications do not do what
The fact is, what Linux does and has always done is the only reasonable
thing to do: the close _will_ tear down the FD, and the error value is
nothing but a warning to the application that there may still be IO
pending (or there may have been failed IO) on the file that the (now
closed) descriptor pointed to.
The application may want to take evasive action (ie try to write the
file again, make a backup, or just warn the user), but the file
descriptor is _gone_.
>That means, if we get an error, we have to loop until the kernel throws
>a BADF error! We can't detect that the file is closed from any other
>error value, because only BADF has a defined behavior.
But your loop is _provably_ incorrect for a threaded application. Your
explicit system call locking approach doesn't work either, because I'm
pretty certain that POSIX already states that open/close are thread
safe, so you can't just invalidate that _other_ standard.
From: Linus Torvalds <email@example.com>
Subject: Re: close return value
Date: Sat, 20 Jul 2002 16:46:09 GMT
On Sat, 20 Jul 2002, Florian Weimer wrote:
> Returning an error and still doing the operation is slightly awkward.
> Are there any other syscalls which do similar things?
mmap(MAP_FIXED) may have already unmapped any underlying old area if an
And EFAULT may have strange behaviour for left-over stuff. If I remember
correctly, at some point, for example, EFAULT on a write to a TCP socket
(if the fault happened in the middle) would still send out the full-sized
packet zero-padded, because not doing so would have screwed up the state
(But EFAULT is a special case in general, it's documented to be undefined
I can't think of any others, but at least close() isn't _completely_
And as you say, we really cannot change it anyway, even if we wanted to
(which I'm personally convinced we do not).