* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) [not found] ` <fa.i1e82rv.1digoa4@ifi.uio.no> @ 2002-07-17 3:46 ` Russ Allbery 0 siblings, 0 replies; 23+ messages in thread From: Russ Allbery @ 2002-07-17 3:46 UTC (permalink / raw) To: Zack Weinberg; +Cc: linux-kernel Zack Weinberg <zack@codesourcery.com> writes: > Consider: There is no guarantee that close will detect errors. Only > NFS and Coda implement f_op->flush methods. And AFS, I believe. (Not in the standard kernel, of course.) -- Russ Allbery (rra@stanford.edu) <http://www.eyrie.org/~eagle/> ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks
@ 2002-07-16 19:38 Thunder from the hill
2002-07-16 23:22 ` close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) Zack Weinberg
0 siblings, 1 reply; 23+ messages in thread
From: Thunder from the hill @ 2002-07-16 19:38 UTC (permalink / raw)
To: Matthias Andree; +Cc: linux-kernel
Hi,
On Tue, 16 Jul 2002, Matthias Andree wrote:
> Indeed, but OTOH, what error is close to report when the file is opened
> read-only?
Well, you can still get EIO, EINTR, EBADF. Whatever you say, disregarding
the close return code is never any good.
Regards,
Thunder
--
(Use http://www.ebb.org/ungeek if you can't decode)
------BEGIN GEEK CODE BLOCK------
Version: 3.12
GCS/E/G/S/AT d- s++:-- a? C++$ ULAVHI++++$ P++$ L++++(+++++)$ E W-$
N--- o? K? w-- O- M V$ PS+ PE- Y- PGP+ t+ 5+ X+ R- !tv b++ DI? !D G
e++++ h* r--- y-
------END GEEK CODE BLOCK------
^ permalink raw reply [flat|nested] 23+ messages in thread* close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-16 19:38 [ANNOUNCE] Ext3 vs Reiserfs benchmarks Thunder from the hill @ 2002-07-16 23:22 ` Zack Weinberg 2002-07-17 1:03 ` Alan Cox 0 siblings, 1 reply; 23+ messages in thread From: Zack Weinberg @ 2002-07-16 23:22 UTC (permalink / raw) To: linux-kernel Thunder wrote: > On Tue, 16 Jul 2002, Matthias Andree wrote: > > Indeed, but OTOH, what error is close to report when the file is > > opened read-only? > > Well, you can still get EIO, EINTR, EBADF. Whatever you say, > disregarding the close return code is never any good. Making use of the close return value is also never any good. Consider: There is no guarantee that close will detect errors. Only NFS and Coda implement f_op->flush methods. For files on all other file systems, sys_close will always return success (assuming the file descriptor was open in the first place); the data may still be sitting in the page cache. If you need the data pushed to the physical disk, you have to call fsync. Consider: If you have called fsync, and it returned successfully, an immediate call to close is guaranteed to return successfully. (Any hypothetical f_op->flush method would have nothing to do; if not, that filesystem does not correctly implement fsync.) Therefore, I would argue that it is wrong for any application ever to inspect close's return value. Either the program does not need data integrity guarantees, or it should be using fsync and paying attention to that instead. There's also an ugly semantic bind if you make close detect errors. If close returns an error other than EBADF, has that file descriptor been closed? The standards do not specify. If it has not been closed, you have a descriptor leak. But if it has been closed, it is too late to recover from the error. [As far as I know, Unix implementations generally do close the descriptor.] The manpage that was quoted earlier in this thread is incorrect in claiming that errors will be detected by close; it should be fixed. zw ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-16 23:22 ` close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) Zack Weinberg @ 2002-07-17 1:03 ` Alan Cox 2002-07-17 0:10 ` Zack Weinberg 2002-07-17 2:22 ` Elladan 0 siblings, 2 replies; 23+ messages in thread From: Alan Cox @ 2002-07-17 1:03 UTC (permalink / raw) To: Zack Weinberg; +Cc: linux-kernel On Wed, 2002-07-17 at 00:22, Zack Weinberg wrote: > Making use of the close return value is also never any good. This is untrue > Consider: There is no guarantee that close will detect errors. Only > NFS and Coda implement f_op->flush methods. For files on all other > file systems, sys_close will always return success (assuming the file > descriptor was open in the first place); the data may still be sitting > in the page cache. If you need the data pushed to the physical disk, > you have to call fsync. close() checking is not about physical disk guarantees. It's about more basic "I/O completed". In some future Linux only close() might tell you about some kinds of I/O error. The fact it doesn't do it now is no excuse for sloppy programming > There's also an ugly semantic bind if you make close detect errors. > If close returns an error other than EBADF, has that file descriptor > been closed? The standards do not specify. If it has not been > closed, you have a descriptor leak. But if it has been closed, it is > too late to recover from the error. [As far as I know, Unix > implementations generally do close the descriptor.] If it bothers you close it again 8) > The manpage that was quoted earlier in this thread is incorrect in > claiming that errors will be detected by close; it should be fixed. The man page matches the stsndard. Implementation may be a subset of the allowed standard right now, but don't program to implementation assumptions, it leads to nasty accidents ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 1:03 ` Alan Cox @ 2002-07-17 0:10 ` Zack Weinberg 2002-07-17 1:45 ` Alan Cox 2002-07-17 8:00 ` Lars Marowsky-Bree 2002-07-17 2:22 ` Elladan 1 sibling, 2 replies; 23+ messages in thread From: Zack Weinberg @ 2002-07-17 0:10 UTC (permalink / raw) To: Alan Cox; +Cc: linux-kernel On Wed, Jul 17, 2002 at 02:03:02AM +0100, Alan Cox wrote: > On Wed, 2002-07-17 at 00:22, Zack Weinberg wrote: > > Making use of the close return value is also never any good. > > This is untrue I beg to differ. > > Consider: There is no guarantee that close will detect errors. Only > > NFS and Coda implement f_op->flush methods. For files on all other > > file systems, sys_close will always return success (assuming the file > > descriptor was open in the first place); the data may still be sitting > > in the page cache. If you need the data pushed to the physical disk, > > you have to call fsync. > > close() checking is not about physical disk guarantees. It's about more > basic "I/O completed". In some future Linux only close() might tell you > about some kinds of I/O error. I think we're talking past each other. My first point is that a portable application cannot rely on close to detect any error. Only fsync guarantees to detect any errors at all (except ENOSPC/EDQUOT, which should come back on write; yes, I know about the buggy NFS implementations that report them only on close). My second point, which you deleted, is that if some hypothetical close implementation reports an error under some circumstances, an immediately preceding fsync call MUST also report the same error under the same circumstances. Therefore, if you've checked the return value of fsync, there's no point in checking the subsequent close; and if you don't care to call fsync, the close return value is useless since it isn't guaranteed to detect anything. > > There's also an ugly semantic bind if you make close detect errors. > > If close returns an error other than EBADF, has that file descriptor > > been closed? The standards do not specify. If it has not been > > closed, you have a descriptor leak. But if it has been closed, it is > > too late to recover from the error. [As far as I know, Unix > > implementations generally do close the descriptor.] > > If it bothers you close it again 8) And watch it come back with an error again, repeat ad infinitum? > > The manpage that was quoted earlier in this thread is incorrect in > > claiming that errors will be detected by close; it should be fixed. > > The man page matches the stsndard. Implementation may be a subset of the > allowed standard right now, but don't program to implementation > assumptions, it leads to nasty accidents You missed the point. The manpage asserts that I/O errors are guaranteed to be detected by close; there is no such guarantee. zw ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 0:10 ` Zack Weinberg @ 2002-07-17 1:45 ` Alan Cox 2002-07-17 18:24 ` Zack Weinberg 2002-07-22 16:42 ` Rogier Wolff 2002-07-17 8:00 ` Lars Marowsky-Bree 1 sibling, 2 replies; 23+ messages in thread From: Alan Cox @ 2002-07-17 1:45 UTC (permalink / raw) To: Zack Weinberg; +Cc: linux-kernel On Wed, 2002-07-17 at 01:10, Zack Weinberg wrote: > My first point is that a portable application cannot rely on close to > detect any error. Only fsync guarantees to detect any errors at all > (except ENOSPC/EDQUOT, which should come back on write; yes, I know > about the buggy NFS implementations that report them only on close). They are not buggy merely inconvenient. The reality of the NFS protocol makes it the only viable way to do it > My second point, which you deleted, is that if some hypothetical close > implementation reports an error under some circumstances, an > immediately preceding fsync call MUST also report the same error under > the same circumstances. I can't think of a case I'd disagree > Therefore, if you've checked the return value of fsync, there's no > point in checking the subsequent close; and if you don't care to call > fsync, the close return value is useless since it isn't guaranteed to > detect anything. If you don't check the return code it might not detect anything. If you do check the return code it might detect something. In fact you contradict yourself IMHO by giving the NFS example. > > If it bothers you close it again 8) > > And watch it come back with an error again, repeat ad infinitum? The use of intelligence doesn't help. Come on I know you aren't a cobol programmer. Check for -EBADF ... > You missed the point. The manpage asserts that I/O errors are > guaranteed to be detected by close; there is no such guarantee. Disagree. It says It is quite possible that errors on a previous write(2) operation are first reported at the final close Not checking the return value when closing the file may lead to silent loss of data. A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a filesystem to flush the buffers when the stream is closed. If you need to be sure that the data is physically stored use fsync(2). (It will depend on the disk hardware at this point.) None of which guarantee what you say, and which agree about the use of fsync being appropriate now and then ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 1:45 ` Alan Cox @ 2002-07-17 18:24 ` Zack Weinberg 2002-07-22 16:42 ` Rogier Wolff 1 sibling, 0 replies; 23+ messages in thread From: Zack Weinberg @ 2002-07-17 18:24 UTC (permalink / raw) To: Alan Cox; +Cc: linux-kernel On Wed, Jul 17, 2002 at 02:45:40AM +0100, Alan Cox wrote: > On Wed, 2002-07-17 at 01:10, Zack Weinberg wrote: > > My first point is that a portable application cannot rely on close to > > detect any error. Only fsync guarantees to detect any errors at all > > (except ENOSPC/EDQUOT, which should come back on write; yes, I know > > about the buggy NFS implementations that report them only on close). > > They are not buggy merely inconvenient. The reality of the NFS protocol > makes it the only viable way to do it You are referring to the way NFSv2 lacks any way to request space allocation on the server without also flushing data to disk? It was my understanding that NFSv2 clients that did not accept the performance hit and do all writes synchronously were considered broken. (since, for instance, POSIX write-visibility guarantees are violated if writes are delayed on the client.) In v3 or v4, the WRITE/COMMIT separation lets the implementor generate prompt ENOSPC and EDQUOT errors without performance penalty. Another thing to keep in mind is that an application is often in a much better position to recover from an error, particularly a disk-full error, if it's reported on write rather than on close. That's just a quality-of-implementation question, though. > > > If it bothers you close it again 8) > > > > And watch it come back with an error again, repeat ad infinitum? > > The use of intelligence doesn't help. Come on I know you aren't a cobol > programmer. Check for -EBADF ... I wasn't talking about EBADF. How does the application know the kernel will ever succeed in closing the file? > Disagree. It says > > It is quite possible that errors on a previous write(2) operation > are first reported at the final close > > Not checking the return value when closing the file may lead to silent > loss of data. > > A successful close does not guarantee that the data has > been successfully saved to disk, as the kernel defers > writes. It is not common for a filesystem to flush the > buffers when the stream is closed. If you need to be sure > that the data is physically stored use fsync(2). (It will > depend on the disk hardware at this point.) > > None of which guarantee what you say, and which agree about the use of > fsync being appropriate now and then That is not the text quoted upthread. Looks like the manpage did get fixed, although I think the current wording is still suboptimal. zw ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 1:45 ` Alan Cox 2002-07-17 18:24 ` Zack Weinberg @ 2002-07-22 16:42 ` Rogier Wolff 1 sibling, 0 replies; 23+ messages in thread From: Rogier Wolff @ 2002-07-22 16:42 UTC (permalink / raw) To: Alan Cox; +Cc: Zack Weinberg, linux-kernel Alan Cox wrote: > > And watch it come back with an error again, repeat ad infinitum? > > The use of intelligence doesn't help. Come on I know you aren't a cobol > programmer. Check for -EBADF ... Huh? My mgetty/sendfax setup did something interesting lately. I had not finished installing it, and I got a fax. It recieved it into /tmp, tried moving it to /var/spool/fax/incoming, failed, and left the tempfile in /tmp. It then mailed me about the recieved fax in /tmp. This is EXACTLY the intelligent behaviour that an application writer can chose for when checking for error codes. Especially "don't unlink your tempfiles" is easy if you get errors on conversion or copying.... Roger. -- ** R.E.Wolff@BitWizard.nl ** http://www.BitWizard.nl/ ** +31-15-2137555 ** *-- BitWizard writes Linux device drivers for any device you may have! --* * There are old pilots, and there are bold pilots. * There are also old, bald pilots. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 0:10 ` Zack Weinberg 2002-07-17 1:45 ` Alan Cox @ 2002-07-17 8:00 ` Lars Marowsky-Bree 2002-07-17 15:49 ` Thunder from the hill 1 sibling, 1 reply; 23+ messages in thread From: Lars Marowsky-Bree @ 2002-07-17 8:00 UTC (permalink / raw) To: Zack Weinberg, Alan Cox; +Cc: linux-kernel On 2002-07-16T17:10:32, Zack Weinberg <zack@codesourcery.com> said: > Therefore, if you've checked the return value of fsync, there's no > point in checking the subsequent close; and if you don't care to call > fsync, the close return value is useless since it isn't guaranteed to > detect anything. There is _always_ a point in checking a return value of non void functions. EOD. Sincerely, Lars Marowsky-Brée <lmb@suse.de> -- Immortality is an adequate definition of high availability for me. --- Gregory F. Pfister ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 8:00 ` Lars Marowsky-Bree @ 2002-07-17 15:49 ` Thunder from the hill 0 siblings, 0 replies; 23+ messages in thread From: Thunder from the hill @ 2002-07-17 15:49 UTC (permalink / raw) To: Lars Marowsky-Bree; +Cc: Zack Weinberg, Alan Cox, linux-kernel Hi, On Tue, 16 Jul 2002, Zack Weinberg wrote: > the close return value is useless since it isn't guaranteed to detect > anything. "Isn't guaranteed to detect anything" is still a lot more encouraging to see if it does detect anything than "Is guaranteed not to detect anything". Regards, Thunder -- (Use http://www.ebb.org/ungeek if you can't decode) ------BEGIN GEEK CODE BLOCK------ Version: 3.12 GCS/E/G/S/AT d- s++:-- a? C++$ ULAVHI++++$ P++$ L++++(+++++)$ E W-$ N--- o? K? w-- O- M V$ PS+ PE- Y- PGP+ t+ 5+ X+ R- !tv b++ DI? !D G e++++ h* r--- y- ------END GEEK CODE BLOCK------ ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 1:03 ` Alan Cox 2002-07-17 0:10 ` Zack Weinberg @ 2002-07-17 2:22 ` Elladan 2002-07-17 2:54 ` Thunder from the hill 2002-07-17 4:17 ` Stevie O 1 sibling, 2 replies; 23+ messages in thread From: Elladan @ 2002-07-17 2:22 UTC (permalink / raw) To: Alan Cox; +Cc: Zack Weinberg, linux-kernel On Wed, Jul 17, 2002 at 02:03:02AM +0100, Alan Cox wrote: > On Wed, 2002-07-17 at 00:22, Zack Weinberg wrote: > > > There's also an ugly semantic bind if you make close detect errors. > > If close returns an error other than EBADF, has that file descriptor > > been closed? The standards do not specify. If it has not been > > closed, you have a descriptor leak. But if it has been closed, it is > > too late to recover from the error. [As far as I know, Unix > > implementations generally do close the descriptor.] > > If it bothers you close it again 8) Consider: Two threads share the file descriptor table. 1. Thread 1 performs close() on a file descriptor. close fails. 2. Thread 2 performs open(). * 3. Thread 1 performs close() again, just to make sure. open() may return any file descriptor not currently in use. Is step 3 necessary? Is it dangerous? The question is, is close guaranteed to work, or isn't it? Case 1: Close is guaranteed to close the file. Thread 2 may have just re-used the file descriptor. Thus, Thread 1 closes a different file in step 3. Thread 2 is now using a bad file descriptor, and becomes very angry because the kernel just said all was right with the world, and then claims there was a mistake. Thread 2 leaves in a huff. Case 2: Close is guaranteed to leave the file open on error. Thread 2 can't have just re-used the descriptor, so the world is ok in that sense. However, Thread 1 *must* perform step 3, or it leaks a descriptor, the tables fill, and the world becomes a frozen wasteland. Case 3: Close may or may not leave it open due to random chance or filesystem peculiarities. Thread 1 may be required to close it twice, or it may be required not to close it twice. It doesn't know! Night is falling! The world is in flames! Aaaaaaugh! I believe this demonstrates the need for a standard, one way, or the other. :-) -J ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 2:22 ` Elladan @ 2002-07-17 2:54 ` Thunder from the hill 2002-07-17 3:00 ` Elladan 2002-07-17 4:17 ` Stevie O 1 sibling, 1 reply; 23+ messages in thread From: Thunder from the hill @ 2002-07-17 2:54 UTC (permalink / raw) To: Elladan; +Cc: Alan Cox, Zack Weinberg, linux-kernel Hi, On Tue, 16 Jul 2002, Elladan wrote: > Two threads share the file descriptor table. > > 1. Thread 1 performs close() on a file descriptor. close fails. > 2. Thread 2 performs open(). > * 3. Thread 1 performs close() again, just to make sure. Thread 2 shouldn't be able to reuse a currently open fd. This application design is seriously broken. Regards, Thunder -- (Use http://www.ebb.org/ungeek if you can't decode) ------BEGIN GEEK CODE BLOCK------ Version: 3.12 GCS/E/G/S/AT d- s++:-- a? C++$ ULAVHI++++$ P++$ L++++(+++++)$ E W-$ N--- o? K? w-- O- M V$ PS+ PE- Y- PGP+ t+ 5+ X+ R- !tv b++ DI? !D G e++++ h* r--- y- ------END GEEK CODE BLOCK------ ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 2:54 ` Thunder from the hill @ 2002-07-17 3:00 ` Elladan 2002-07-17 3:10 ` Thunder from the hill 0 siblings, 1 reply; 23+ messages in thread From: Elladan @ 2002-07-17 3:00 UTC (permalink / raw) To: Thunder from the hill; +Cc: Elladan, Alan Cox, Zack Weinberg, linux-kernel On Tue, Jul 16, 2002 at 08:54:54PM -0600, Thunder from the hill wrote: > Hi, > > On Tue, 16 Jul 2002, Elladan wrote: > > Two threads share the file descriptor table. > > > > 1. Thread 1 performs close() on a file descriptor. close fails. > > 2. Thread 2 performs open(). > > * 3. Thread 1 performs close() again, just to make sure. > > Thread 2 shouldn't be able to reuse a currently open fd. This application > design is seriously broken. No. Thread 2 doesn't manage the file descriptor table, the kernel does. Whether the kernel may re-use the descriptor or not depends on whether the descriptor is closed or not. The kernel knows, but unless close() behaves in a defined way, the application does not at this point. Thus, step 3 may either be required, forbidden, or undefined. -J ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 3:00 ` Elladan @ 2002-07-17 3:10 ` Thunder from the hill 2002-07-17 3:31 ` Elladan 0 siblings, 1 reply; 23+ messages in thread From: Thunder from the hill @ 2002-07-17 3:10 UTC (permalink / raw) To: Elladan; +Cc: Thunder from the hill, Alan Cox, Zack Weinberg, linux-kernel Hi, On Tue, 16 Jul 2002, Elladan wrote: > > Thread 2 shouldn't be able to reuse a currently open fd. This application > > design is seriously broken. Okay, again. It's about doing a second close() in case the first one fails with EAGAIN. If we have to do it again, the filehandle is not closed, and if the filehandle is not closed, the kernel knows that, and if the kernel knows that the filehandle is still open, it won't get reassigned. Problem gone. Regards, Thunder -- (Use http://www.ebb.org/ungeek if you can't decode) ------BEGIN GEEK CODE BLOCK------ Version: 3.12 GCS/E/G/S/AT d- s++:-- a? C++$ ULAVHI++++$ P++$ L++++(+++++)$ E W-$ N--- o? K? w-- O- M V$ PS+ PE- Y- PGP+ t+ 5+ X+ R- !tv b++ DI? !D G e++++ h* r--- y- ------END GEEK CODE BLOCK------ ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 3:10 ` Thunder from the hill @ 2002-07-17 3:31 ` Elladan 0 siblings, 0 replies; 23+ messages in thread From: Elladan @ 2002-07-17 3:31 UTC (permalink / raw) To: Thunder from the hill; +Cc: Elladan, Alan Cox, Zack Weinberg, linux-kernel On Tue, Jul 16, 2002 at 09:10:49PM -0600, Thunder from the hill wrote: > Hi, > > On Tue, 16 Jul 2002, Elladan wrote: > > > Thread 2 shouldn't be able to reuse a currently open fd. This application > > > design is seriously broken. > > Okay, again. It's about doing a second close() in case the first one fails > with EAGAIN. If we have to do it again, the filehandle is not closed, and > if the filehandle is not closed, the kernel knows that, and if the kernel > knows that the filehandle is still open, it won't get reassigned. Problem > gone. This is case 2, "Close is guaranteed to leave the file open on error." In this case, all applications are required to reissue close commands upon certain errors, or leak a file descriptor. This would be a well defined behavior, though perhaps error prone. However, note that this is manifestly different from case 1, "Close is guaranteed to close the file the first time." If the system behaves via case 1, closing the handle again is broken as the example illustrated. The worst, of course, would be undefined behavior for close. In this case, the application effectively can't do the right thing without extreme measures. -J ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 2:22 ` Elladan 2002-07-17 2:54 ` Thunder from the hill @ 2002-07-17 4:17 ` Stevie O 2002-07-17 4:38 ` Elladan 1 sibling, 1 reply; 23+ messages in thread From: Stevie O @ 2002-07-17 4:17 UTC (permalink / raw) To: Elladan, Alan Cox; +Cc: Zack Weinberg, linux-kernel At 07:22 PM 7/16/2002 -0700, Elladan wrote: > 1. Thread 1 performs close() on a file descriptor. close fails. > 2. Thread 2 performs open(). >* 3. Thread 1 performs close() again, just to make sure. > > >open() may return any file descriptor not currently in use. I'm confused here... the only way close() can fail is if the file descriptor is invalid (EBADF); wouldn't it be rather stupid to close() a known-to-be-bad descriptor? -- Stevie-O Real programmers use COPY CON PROGRAM.EXE ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 4:17 ` Stevie O @ 2002-07-17 4:38 ` Elladan 2002-07-17 14:39 ` Andreas Schwab 2002-07-17 17:17 ` Andries Brouwer 0 siblings, 2 replies; 23+ messages in thread From: Elladan @ 2002-07-17 4:38 UTC (permalink / raw) To: Stevie O; +Cc: Elladan, Alan Cox, Zack Weinberg, linux-kernel On Wed, Jul 17, 2002 at 12:17:40AM -0400, Stevie O wrote: > At 07:22 PM 7/16/2002 -0700, Elladan wrote: > > 1. Thread 1 performs close() on a file descriptor. close fails. > > 2. Thread 2 performs open(). > >* 3. Thread 1 performs close() again, just to make sure. > > > > > >open() may return any file descriptor not currently in use. > > I'm confused here... the only way close() can fail is if the file > descriptor is invalid (EBADF); wouldn't it be rather stupid to close() > a known-to-be-bad descriptor? Well, obviously, if that's the case. However, the man page for close(2) doesn't agree (see below). close() is allowed to return EBADF, EINTR, or EIO. The question is, does the OS standard guarantee that the fd is closed, even if close() returns EINTR or EIO? Just going by the normal usage of EINTR, one might think otherwise. It doesn't appear to be documented one way or another. Alan said you could just issue close again to make sure - the example shows that this is not the case. A second close is either required or forbidden in that example - and the behavior has to be well defined or you won't know which to do. -J NAME close - close a file descriptor SYNOPSIS #include <unistd.h> int close(int fd); DESCRIPTION close closes a file descriptor, so that it no longer refers to any file and may be reused. Any locks held on the file it was associated with, and owned by the process, are removed (regardless of the file descriptor that was used to obtain the lock). If fd is the last copy of a particular file descriptor the resources associated with it are freed; if the descriptor was the last reference to a file which has been removed using unlink(2) the file is deleted. RETURN VALUE close returns zero on success, or -1 if an error occurred. ERRORS EBADF fd isn't a valid open file descriptor. EINTR The close() call was interrupted by a signal. EIO An I/O error occurred. CONFORMING TO SVr4, SVID, POSIX, X/OPEN, BSD 4.3. SVr4 documents an additional ENOLINK error condition. NOTES Not checking the return value of close is a common but nevertheless serious programming error. File system implementations which use techniques as `write-behind' to increase performance may lead to write(2) succeeding, although the data has not been written yet. The error status may be reported at a later write operation, but it is guaranteed to be reported on closing the file. Not checking the return value when closing the file may lead to silent loss of data. This can especially be observed with NFS and disk quotas. A successful close does not guarantee that the data has been successfully saved to disk, as the kernel defers writes. It is not common for a filesystem to flush the buffers when the stream is closed. If you need to be sure that the data is physically stored use fsync(2) or sync(2), they will get you closer to that goal (it will depend on the disk hardware at this point). SEE ALSO open(2), fcntl(2), shutdown(2), unlink(2), fclose(3) ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 4:38 ` Elladan @ 2002-07-17 14:39 ` Andreas Schwab 2002-07-17 16:49 ` Elladan 2002-07-17 17:17 ` Andries Brouwer 1 sibling, 1 reply; 23+ messages in thread From: Andreas Schwab @ 2002-07-17 14:39 UTC (permalink / raw) To: Elladan; +Cc: Stevie O, Alan Cox, Zack Weinberg, linux-kernel Elladan <elladan@eskimo.com> writes: |> On Wed, Jul 17, 2002 at 12:17:40AM -0400, Stevie O wrote: |> > At 07:22 PM 7/16/2002 -0700, Elladan wrote: |> > > 1. Thread 1 performs close() on a file descriptor. close fails. |> > > 2. Thread 2 performs open(). |> > >* 3. Thread 1 performs close() again, just to make sure. |> > > |> > > |> > >open() may return any file descriptor not currently in use. |> > |> > I'm confused here... the only way close() can fail is if the file |> > descriptor is invalid (EBADF); wouldn't it be rather stupid to close() |> > a known-to-be-bad descriptor? |> |> Well, obviously, if that's the case. However, the man page for close(2) |> doesn't agree (see below). close() is allowed to return EBADF, EINTR, |> or EIO. |> |> The question is, does the OS standard guarantee that the fd is closed, |> even if close() returns EINTR or EIO? Just going by the normal usage of |> EINTR, one might think otherwise. It doesn't appear to be documented |> one way or another. POSIX says the state of the file descriptor when close fails (with errno != EBADF) is unspecified, which means: The value or behavior may vary among implementations that conform to IEEE Std 1003.1-2001. An application should not rely on the existence or validity of the value or behavior. An application that relies on any particular value or behavior cannot be assured to be portable across conforming implementations. Andreas. -- Andreas Schwab, SuSE Labs, schwab@suse.de SuSE Linux AG, Deutschherrnstr. 15-19, D-90429 Nürnberg Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 14:39 ` Andreas Schwab @ 2002-07-17 16:49 ` Elladan 2002-07-17 17:43 ` Linus Torvalds 0 siblings, 1 reply; 23+ messages in thread From: Elladan @ 2002-07-17 16:49 UTC (permalink / raw) To: Andreas Schwab; +Cc: Elladan, Stevie O, Alan Cox, Zack Weinberg, linux-kernel On Wed, Jul 17, 2002 at 04:39:28PM +0200, Andreas Schwab wrote: > Elladan <elladan@eskimo.com> writes: > > |> On Wed, Jul 17, 2002 at 12:17:40AM -0400, Stevie O wrote: > |> > At 07:22 PM 7/16/2002 -0700, Elladan wrote: > |> > > 1. Thread 1 performs close() on a file descriptor. close fails. > |> > > 2. Thread 2 performs open(). > |> > >* 3. Thread 1 performs close() again, just to make sure. > |> > > > |> > > > |> > >open() may return any file descriptor not currently in use. > |> > > |> > I'm confused here... the only way close() can fail is if the file > |> > descriptor is invalid (EBADF); wouldn't it be rather stupid to close() > |> > a known-to-be-bad descriptor? > |> > |> Well, obviously, if that's the case. However, the man page for close(2) > |> doesn't agree (see below). close() is allowed to return EBADF, EINTR, > |> or EIO. > |> > |> The question is, does the OS standard guarantee that the fd is closed, > |> even if close() returns EINTR or EIO? Just going by the normal usage of > |> EINTR, one might think otherwise. It doesn't appear to be documented > |> one way or another. > > POSIX says the state of the file descriptor when close fails (with errno > != EBADF) is unspecified, which means: > > The value or behavior may vary among implementations that conform to > IEEE Std 1003.1-2001. An application should not rely on the existence > or validity of the value or behavior. An application that relies on > any particular value or behavior cannot be assured to be portable > across conforming implementations. This doesn't mean an OS shouldn't specify the behavior. Just because the cross-platform standard leaves it unspecified doesn't mean the OS should. 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: int ret; do { ret = close(fd); } while(ret == -1 && errno != EBADF); 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. This would sort of work, though of course be hideous, for a single threaded app. Now consider a multithreaded app. To correctly implement this we have to lock around all calls to close and open/socket/dup/pipe/creat/etc... This is clearly ridiculous, and not at all as intended. Either standard will work for an OS (though guaranteeing close the first time is much simpler all around), but it needs to be specified and stuck to, or you get horrible things like this to work around a bad spec: void lock_syscalls(); void unlock_syscalls(); int threadsafe_open(const char *file, int flags, mode_t mode) { int fd; lock_syscalls(); fd = open(file, flags, mode); unlock_syscalls(); return fd; } int threadsafe_close(int fd) { int ret; lock_syscalls(); do { ret = close(fd); } while(ret == -1 && errno != EBADF); unlock_syscalls(); return ret; } int threadsafe_socket() ... int threadsafe_pipe() ... int threadsafe_dup() ... int threadsafe_creat() ... int threadsafe_socketpair() ... int threadsafe_accept() ... -J ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 16:49 ` Elladan @ 2002-07-17 17:43 ` Linus Torvalds 2002-07-17 22:07 ` Elladan 2002-07-18 9:48 ` Ketil Froyn 0 siblings, 2 replies; 23+ messages in thread From: Linus Torvalds @ 2002-07-17 17:43 UTC (permalink / raw) To: linux-kernel In article <20020717164933.GA2136@eskimo.com>, Elladan <elladan@eskimo.com> 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: > >int ret; >do { > ret = close(fd); >} while(ret == -1 && errno != EBADF); NO. 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 you suggest. 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. Linus ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 17:43 ` Linus Torvalds @ 2002-07-17 22:07 ` Elladan 2002-07-18 9:48 ` Ketil Froyn 1 sibling, 0 replies; 23+ messages in thread From: Elladan @ 2002-07-17 22:07 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel On Wed, Jul 17, 2002 at 05:43:57PM +0000, Linus Torvalds wrote: > In article <20020717164933.GA2136@eskimo.com>, > Elladan <elladan@eskimo.com> 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: > > > >int ret; > >do { > > ret = close(fd); > >} while(ret == -1 && errno != EBADF); > > NO. > > 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. That somebody was me. It appears we're in extremely violent agreement on this issue. We both agree the code I wrote is crap. :-) -J ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 17:43 ` Linus Torvalds 2002-07-17 22:07 ` Elladan @ 2002-07-18 9:48 ` Ketil Froyn 1 sibling, 0 replies; 23+ messages in thread From: Ketil Froyn @ 2002-07-18 9:48 UTC (permalink / raw) To: Linus Torvalds; +Cc: linux-kernel On Wed, 17 Jul 2002, Linus Torvalds wrote: > >int ret; > >do { > > ret = close(fd); > >} while(ret == -1 && errno != EBADF); > > NO. > > 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 > you suggest. > > 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. Is this what happens when EINTR is received as well? If so, is there any point to EINTR? Ie. close() was interrupted, but finished anyway. Would any application care? If there is any pending IO when this happens, is it possible to find out when this is finished? If not, an MTA getting this would have to temporarily defer the mail it received and hope it doesn't get an EINTR on close() next time, I guess. Ketil ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 4:38 ` Elladan 2002-07-17 14:39 ` Andreas Schwab @ 2002-07-17 17:17 ` Andries Brouwer 2002-07-17 17:51 ` Richard Gooch 1 sibling, 1 reply; 23+ messages in thread From: Andries Brouwer @ 2002-07-17 17:17 UTC (permalink / raw) To: Elladan; +Cc: Stevie O, Alan Cox, Zack Weinberg, linux-kernel On Tue, Jul 16, 2002 at 09:38:53PM -0700, Elladan wrote: > The question is, does the OS standard guarantee that the fd is closed, > even if close() returns EINTR or EIO? Just going by the normal usage of > EINTR, one might think otherwise. It doesn't appear to be documented > one way or another. > > Alan said you could just issue close again to make sure - the example > shows that this is not the case. A second close is either required or > forbidden in that example - and the behavior has to be well defined or > you won't know which to do. No, the behaviour is not well-defined at all. The standard explicitly leaves undefined what happens when close returns EINTR or EIO. ^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) 2002-07-17 17:17 ` Andries Brouwer @ 2002-07-17 17:51 ` Richard Gooch 0 siblings, 0 replies; 23+ messages in thread From: Richard Gooch @ 2002-07-17 17:51 UTC (permalink / raw) To: Andries Brouwer; +Cc: Elladan, Stevie O, Alan Cox, Zack Weinberg, linux-kernel Andries Brouwer writes: > On Tue, Jul 16, 2002 at 09:38:53PM -0700, Elladan wrote: > > > The question is, does the OS standard guarantee that the fd is closed, > > even if close() returns EINTR or EIO? Just going by the normal usage of > > EINTR, one might think otherwise. It doesn't appear to be documented > > one way or another. > > > > Alan said you could just issue close again to make sure - the example > > shows that this is not the case. A second close is either required or > > forbidden in that example - and the behavior has to be well defined or > > you won't know which to do. > > No, the behaviour is not well-defined at all. > The standard explicitly leaves undefined what happens when close > returns EINTR or EIO. However, the only sane thing to do is to explicitly define one way or another. The standard is broken. Consider a threaded application, where one thread tries to call close(), gets an error and re-tries, because it's not sure if the fd was closed or not. If the fd *is* closed, and the thread loops calling close(), checking for EBADF, there is a race if another thread tries calling open()/creat()/dup(). The ambiguity in the standard thus results in the impossibility of writing a race-free application. And no, forcing the application to protect system calls with mutexes isn't a solution. Linux should define explicitly what happens on error return from close(). Let that be the new standard. Regards, Richard.... Permanent: rgooch@atnf.csiro.au Current: rgooch@ras.ucalgary.ca ^ permalink raw reply [flat|nested] 23+ messages in thread
end of thread, other threads:[~2002-07-22 16:39 UTC | newest]
Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <fa.lfdnrtv.5h8i1j@ifi.uio.no>
[not found] ` <fa.i1e82rv.1digoa4@ifi.uio.no>
2002-07-17 3:46 ` close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) Russ Allbery
2002-07-16 19:38 [ANNOUNCE] Ext3 vs Reiserfs benchmarks Thunder from the hill
2002-07-16 23:22 ` close return value (was Re: [ANNOUNCE] Ext3 vs Reiserfs benchmarks) Zack Weinberg
2002-07-17 1:03 ` Alan Cox
2002-07-17 0:10 ` Zack Weinberg
2002-07-17 1:45 ` Alan Cox
2002-07-17 18:24 ` Zack Weinberg
2002-07-22 16:42 ` Rogier Wolff
2002-07-17 8:00 ` Lars Marowsky-Bree
2002-07-17 15:49 ` Thunder from the hill
2002-07-17 2:22 ` Elladan
2002-07-17 2:54 ` Thunder from the hill
2002-07-17 3:00 ` Elladan
2002-07-17 3:10 ` Thunder from the hill
2002-07-17 3:31 ` Elladan
2002-07-17 4:17 ` Stevie O
2002-07-17 4:38 ` Elladan
2002-07-17 14:39 ` Andreas Schwab
2002-07-17 16:49 ` Elladan
2002-07-17 17:43 ` Linus Torvalds
2002-07-17 22:07 ` Elladan
2002-07-18 9:48 ` Ketil Froyn
2002-07-17 17:17 ` Andries Brouwer
2002-07-17 17:51 ` Richard Gooch
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®