* close(2) with EINTR has been changed by POSIX.1-2024 @ 2025-05-15 21:33 Alejandro Colomar 2025-05-16 10:48 ` Jan Kara 0 siblings, 1 reply; 25+ messages in thread From: Alejandro Colomar @ 2025-05-15 21:33 UTC (permalink / raw) To: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel, linux-api Cc: linux-man [-- Attachment #1: Type: text/plain, Size: 2238 bytes --] Hi, I'm updating the manual pages for POSIX.1-2024, and have some doubts about close(2). The manual page for close(2) says (conforming to POSIX.1-2008): The EINTR error is a somewhat special case. Regarding the EINTR error, POSIX.1‐2008 says: If close() is interrupted by a signal that is to be caught, it shall return -1 with errno set to EINTR and the state of fildes is unspecified. This permits the behavior that occurs on Linux and many other implementations, where, as with other errors that may be re‐ ported by close(), the file descriptor is guaranteed to be closed. However, it also permits another possibility: that the implementation returns an EINTR error and keeps the file de‐ scriptor open. (According to its documentation, HP‐UX’s close() does this.) The caller must then once more use close() to close the file descriptor, to avoid file descriptor leaks. This di‐ vergence in implementation behaviors provides a difficult hurdle for portable applications, since on many implementations, close() must not be called again after an EINTR error, and on at least one, close() must be called again. There are plans to ad‐ dress this conundrum for the next major release of the POSIX.1 standard. TL;DR: close(2) with EINTR is allowed to either leave the fd open or closed, and Linux leaves it closed, while others (HP-UX only?) leaves it open. Now, POSIX.1-2024 says: If close() is interrupted by a signal that is to be caught, then it is unspecified whether it returns -1 with errno set to [EINTR] and fildes remaining open, or returns -1 with errno set to [EINPROGRESS] and fildes being closed, or returns 0 to indicate successful completion; [...] <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> Which seems to bless HP-UX and screw all the others, requiring them to report EINPROGRESS. Was there any discussion about what to do in the Linux kernel? Have a lovely night! Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-15 21:33 close(2) with EINTR has been changed by POSIX.1-2024 Alejandro Colomar @ 2025-05-16 10:48 ` Jan Kara 2025-05-16 12:11 ` Alejandro Colomar ` (4 more replies) 0 siblings, 5 replies; 25+ messages in thread From: Jan Kara @ 2025-05-16 10:48 UTC (permalink / raw) To: Alejandro Colomar Cc: Alexander Viro, Christian Brauner, Jan Kara, linux-fsdevel, linux-api, linux-man Hi! On Thu 15-05-25 23:33:22, Alejandro Colomar wrote: > I'm updating the manual pages for POSIX.1-2024, and have some doubts > about close(2). The manual page for close(2) says (conforming to > POSIX.1-2008): > > The EINTR error is a somewhat special case. Regarding the EINTR > error, POSIX.1‐2008 says: > > If close() is interrupted by a signal that is to be > caught, it shall return -1 with errno set to EINTR and > the state of fildes is unspecified. > > This permits the behavior that occurs on Linux and many other > implementations, where, as with other errors that may be re‐ > ported by close(), the file descriptor is guaranteed to be > closed. However, it also permits another possibility: that the > implementation returns an EINTR error and keeps the file de‐ > scriptor open. (According to its documentation, HP‐UX’s close() > does this.) The caller must then once more use close() to close > the file descriptor, to avoid file descriptor leaks. This di‐ > vergence in implementation behaviors provides a difficult hurdle > for portable applications, since on many implementations, > close() must not be called again after an EINTR error, and on at > least one, close() must be called again. There are plans to ad‐ > dress this conundrum for the next major release of the POSIX.1 > standard. > > TL;DR: close(2) with EINTR is allowed to either leave the fd open or > closed, and Linux leaves it closed, while others (HP-UX only?) leaves it > open. > > Now, POSIX.1-2024 says: > > If close() is interrupted by a signal that is to be caught, then > it is unspecified whether it returns -1 with errno set to > [EINTR] and fildes remaining open, or returns -1 with errno set > to [EINPROGRESS] and fildes being closed, or returns 0 to > indicate successful completion; [...] > > <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> > > Which seems to bless HP-UX and screw all the others, requiring them to > report EINPROGRESS. > > Was there any discussion about what to do in the Linux kernel? I'm not aware of any discussions but indeed we are returning EINTR while closing the fd. Frankly, changing the error code we return in that case is really asking for userspace regressions so I'm of the opinion we just ignore the standard as in my opinion it goes against a long established reality. Honza -- Jan Kara <jack@suse.com> SUSE Labs, CR ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-16 10:48 ` Jan Kara @ 2025-05-16 12:11 ` Alejandro Colomar 2025-05-16 12:52 ` [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 Alejandro Colomar 2025-05-16 12:41 ` close(2) with EINTR has been changed by POSIX.1-2024 Mateusz Guzik ` (3 subsequent siblings) 4 siblings, 1 reply; 25+ messages in thread From: Alejandro Colomar @ 2025-05-16 12:11 UTC (permalink / raw) To: Jan Kara Cc: Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, linux-man [-- Attachment #1: Type: text/plain, Size: 844 bytes --] Hi Jan! On Fri, May 16, 2025 at 12:48:56PM +0200, Jan Kara wrote: > > <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> > > > > Which seems to bless HP-UX and screw all the others, requiring them to > > report EINPROGRESS. > > > > Was there any discussion about what to do in the Linux kernel? > > I'm not aware of any discussions but indeed we are returning EINTR while > closing the fd. Frankly, changing the error code we return in that case is > really asking for userspace regressions so I'm of the opinion we just > ignore the standard as in my opinion it goes against a long established > reality. Yep, sounds like what I was expecting. I'll document that we'll ignore the new POSIX for close(2) on purpose. Thanks! Have a lovely day! Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 12:11 ` Alejandro Colomar @ 2025-05-16 12:52 ` Alejandro Colomar 2025-05-16 13:05 ` Rich Felker 0 siblings, 1 reply; 25+ messages in thread From: Alejandro Colomar @ 2025-05-16 12:52 UTC (permalink / raw) Cc: Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, Rich Felker, linux-fsdevel, linux-api, libc-alpha POSIX.1-2024 now mandates a behavior different from what Linux (and many other implementations) does. It requires that we report EINPROGRESS for what now is EINTR. There are no plans to conform to POSIX.1-2024 within the Linux kernel, so document this divergence. Keep POSIX.1-2008 as the standard to which we conform in STANDARDS. Link: <https://sourceware.org/bugzilla/show_bug.cgi?id=14627> Link: <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> Cc: Jan Kara <jack@suse.cz> Cc: Alexander Viro <viro@zeniv.linux.org.uk> Cc: Christian Brauner <brauner@kernel.org> Cc: Rich Felker <dalias@libc.org> Cc: <linux-fsdevel@vger.kernel.org> Cc: <linux-api@vger.kernel.org> Cc: <libc-alpha@sourceware.org> Signed-off-by: Alejandro Colomar <alx@kernel.org> --- Hi, I've prepared this draft for discussion. While doing so, I've noticed the glibc bug ticket, which sounds possibly reasonable: returning 0 instead of reporting an error on EINTR. That would be an option that would make us conforming to POSIX.1-2024. And given that a user can (and must) do nothing after seeing EINTR, returning 0 wouldn't change things. So, I'll leave this patch open for discussion. Have a lovely day! Alex man/man2/close.2 | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/man/man2/close.2 b/man/man2/close.2 index b25ea4de9..9d5e26eed 100644 --- a/man/man2/close.2 +++ b/man/man2/close.2 @@ -191,10 +191,7 @@ .SS Dealing with error returns from close() meaning that the file descriptor was invalid) even if they subsequently report an error on return from .BR close (). -POSIX.1 is currently silent on this point, -but there are plans to mandate this behavior in the next major release -.\" Issue 8 -of the standard. +POSIX.1-2008 was silent on this point. .P A careful programmer who wants to know about I/O errors may precede .BR close () @@ -206,7 +203,7 @@ .SS Dealing with error returns from close() error is a somewhat special case. Regarding the .B EINTR -error, POSIX.1-2008 says: +error, POSIX.1-2008 said: .P .RS If @@ -243,16 +240,10 @@ .SS Dealing with error returns from close() error, and on at least one, .BR close () must be called again. -There are plans to address this conundrum for -the next major release of the POSIX.1 standard. -.\" FIXME . for later review when Issue 8 is one day released... -.\" POSIX proposes further changes for EINTR -.\" http://austingroupbugs.net/tag_view_page.php?tag_id=8 -.\" http://austingroupbugs.net/view.php?id=529 -.\" -.\" FIXME . -.\" Review the following glibc bug later -.\" https://sourceware.org/bugzilla/show_bug.cgi?id=14627 +.P +POSIX.1-2024 standardized the behavior of HP-UX, +making Linux and many other implementations non-conforming. +There are no plans to change the behavior on Linux. .SH SEE ALSO .BR close_range (2), .BR fcntl (2), Range-diff against v0: -: --------- > 1: efaffc5a4 man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 base-commit: 978b017d93e4e32b752b33877e44a8365644630c -- 2.49.0 ^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 12:52 ` [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 Alejandro Colomar @ 2025-05-16 13:05 ` Rich Felker 2025-05-16 14:20 ` Theodore Ts'o 2025-05-16 14:39 ` Vincent Lefevre 0 siblings, 2 replies; 25+ messages in thread From: Rich Felker @ 2025-05-16 13:05 UTC (permalink / raw) To: Alejandro Colomar Cc: Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On Fri, May 16, 2025 at 02:52:05PM +0200, Alejandro Colomar wrote: > POSIX.1-2024 now mandates a behavior different from what Linux (and many > other implementations) does. It requires that we report EINPROGRESS for > what now is EINTR. > > There are no plans to conform to POSIX.1-2024 within the Linux kernel, > so document this divergence. Keep POSIX.1-2008 as the standard to > which we conform in STANDARDS. > > Link: <https://sourceware.org/bugzilla/show_bug.cgi?id=14627> > Link: <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> > Cc: Jan Kara <jack@suse.cz> > Cc: Alexander Viro <viro@zeniv.linux.org.uk> > Cc: Christian Brauner <brauner@kernel.org> > Cc: Rich Felker <dalias@libc.org> > Cc: <linux-fsdevel@vger.kernel.org> > Cc: <linux-api@vger.kernel.org> > Cc: <libc-alpha@sourceware.org> > Signed-off-by: Alejandro Colomar <alx@kernel.org> > --- > > Hi, > > I've prepared this draft for discussion. While doing so, I've noticed > the glibc bug ticket, which sounds possibly reasonable: returning 0 > instead of reporting an error on EINTR. That would be an option that > would make us conforming to POSIX.1-2024. And given that a user can > (and must) do nothing after seeing EINTR, returning 0 wouldn't change > things. > > So, I'll leave this patch open for discussion. FWIW musl adopted the EINPROGRESS as soon as we were made aware of the issue, and later changed it to returning 0 since applications (particularly, any written prior to this interpretation) are prone to interpret EINPROGRESS as an error condition rather than success and possibly misinterpret it as meaning the fd is still open and valid to pass to close again. In general, raw kernel interfaces do not conform to any version of POSIX; they're just a low-impedance-mismatch set of inferfaces that facilitate implementing POSIX at the userspace libc layer. So I don't think this should be documented as "Linux doesn't conform" but (hopefully, once glibc fixes this) "old versions of glibc did not conform". Rich ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 13:05 ` Rich Felker @ 2025-05-16 14:20 ` Theodore Ts'o 2025-05-17 5:46 ` Alejandro Colomar 2025-05-16 14:39 ` Vincent Lefevre 1 sibling, 1 reply; 25+ messages in thread From: Theodore Ts'o @ 2025-05-16 14:20 UTC (permalink / raw) To: Rich Felker Cc: Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On Fri, May 16, 2025 at 09:05:47AM -0400, Rich Felker wrote: > In general, raw kernel interfaces do not conform to any version of > POSIX; they're just a low-impedance-mismatch set of inferfaces that > facilitate implementing POSIX at the userspace libc layer. So I don't > think this should be documented as "Linux doesn't conform" but > (hopefully, once glibc fixes this) "old versions of glibc did not > conform". If glibc maintainers want to deal with breaking userspace, then as a kernel developer, I'm happy to let them deal with the angry/disappointed users and application programmers. :-) - Ted ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 14:20 ` Theodore Ts'o @ 2025-05-17 5:46 ` Alejandro Colomar 2025-05-17 13:03 ` Alejandro Colomar 0 siblings, 1 reply; 25+ messages in thread From: Alejandro Colomar @ 2025-05-17 5:46 UTC (permalink / raw) To: Theodore Ts'o Cc: Rich Felker, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha [-- Attachment #1: Type: text/plain, Size: 1912 bytes --] Hi Ted, Rich, On Fri, May 16, 2025 at 09:05:47AM -0400, Rich Felker wrote: > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > issue, and later changed it to returning 0 since applications > (particularly, any written prior to this interpretation) are prone to > interpret EINPROGRESS as an error condition rather than success and > possibly misinterpret it as meaning the fd is still open and valid to > pass to close again. Hmmm, this page will need a kernel/libc differences section where I should explain this. On Fri, May 16, 2025 at 10:20:24AM -0400, Theodore Ts'o wrote: > On Fri, May 16, 2025 at 09:05:47AM -0400, Rich Felker wrote: > > > In general, raw kernel interfaces do not conform to any version of > > POSIX; they're just a low-impedance-mismatch set of inferfaces that > > facilitate implementing POSIX at the userspace libc layer. So I don't > > think this should be documented as "Linux doesn't conform" but > > (hopefully, once glibc fixes this) "old versions of glibc did not > > conform". > > If glibc maintainers want to deal with breaking userspace, then as a > kernel developer, I'm happy to let them deal with the > angry/disappointed users and application programmers. :-) Which breakage do you expect from the behavior that musl has chosen? I agree that the POSIX invention of EINPROGRESS is something that would break users. However, in removing the error completely and making it a success, I don't see the same problem. That is, if a program calls close(2) and sees a return of 0, or sees a return of -1 with EINTR on Linux, both mean "the file descriptor has been closed, and the contents of the file will *eventually* reach the file". In which cases do you expect any existing Linux program to behave differently on 0 and on EINTR? Have a lovely day! Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-17 5:46 ` Alejandro Colomar @ 2025-05-17 13:03 ` Alejandro Colomar 2025-05-17 13:43 ` Rich Felker 0 siblings, 1 reply; 25+ messages in thread From: Alejandro Colomar @ 2025-05-17 13:03 UTC (permalink / raw) To: Theodore Ts'o Cc: Rich Felker, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha [-- Attachment #1: Type: text/plain, Size: 2731 bytes --] Hi, On Sat, May 17, 2025 at 07:46:48AM +0200, Alejandro Colomar wrote: > Hi Ted, Rich, > > On Fri, May 16, 2025 at 09:05:47AM -0400, Rich Felker wrote: > > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > > issue, and later changed it to returning 0 since applications > > (particularly, any written prior to this interpretation) are prone to > > interpret EINPROGRESS as an error condition rather than success and > > possibly misinterpret it as meaning the fd is still open and valid to > > pass to close again. BTW, I don't think that's a correct interpretation. The manual page clearly says after close(2), even on error, the fd is closed and not usable. The issue I see is a program thinking it failed and trying to copy the file again or reporting an error. On the other hand, as Vincent said, maybe this is not so bad. For certain files, fsync(2) is only described for storage devices, so in some cases there's no clear way to make sure close(2) won't fail after EINTR (maybe calling sync(2)?). So, maybe considering it an error wouldn't be a terrible idea. I don't know. Cheers, Alex > > Hmmm, this page will need a kernel/libc differences section where I > should explain this. > > On Fri, May 16, 2025 at 10:20:24AM -0400, Theodore Ts'o wrote: > > On Fri, May 16, 2025 at 09:05:47AM -0400, Rich Felker wrote: > > > > > In general, raw kernel interfaces do not conform to any version of > > > POSIX; they're just a low-impedance-mismatch set of inferfaces that > > > facilitate implementing POSIX at the userspace libc layer. So I don't > > > think this should be documented as "Linux doesn't conform" but > > > (hopefully, once glibc fixes this) "old versions of glibc did not > > > conform". > > > > If glibc maintainers want to deal with breaking userspace, then as a > > kernel developer, I'm happy to let them deal with the > > angry/disappointed users and application programmers. :-) > > Which breakage do you expect from the behavior that musl has chosen? > > I agree that the POSIX invention of EINPROGRESS is something that would > break users. However, in removing the error completely and making it a > success, I don't see the same problem. That is, if a program calls > close(2) and sees a return of 0, or sees a return of -1 with EINTR on > Linux, both mean "the file descriptor has been closed, and the contents > of the file will *eventually* reach the file". > > In which cases do you expect any existing Linux program to behave > differently on 0 and on EINTR? > > > Have a lovely day! > Alex > > -- > <https://www.alejandro-colomar.es/> -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-17 13:03 ` Alejandro Colomar @ 2025-05-17 13:43 ` Rich Felker 0 siblings, 0 replies; 25+ messages in thread From: Rich Felker @ 2025-05-17 13:43 UTC (permalink / raw) To: Alejandro Colomar Cc: Theodore Ts'o, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On Sat, May 17, 2025 at 03:03:52PM +0200, Alejandro Colomar wrote: > Hi, > > On Sat, May 17, 2025 at 07:46:48AM +0200, Alejandro Colomar wrote: > > Hi Ted, Rich, > > > > On Fri, May 16, 2025 at 09:05:47AM -0400, Rich Felker wrote: > > > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > > > issue, and later changed it to returning 0 since applications > > > (particularly, any written prior to this interpretation) are prone to > > > interpret EINPROGRESS as an error condition rather than success and > > > possibly misinterpret it as meaning the fd is still open and valid to > > > pass to close again. > > BTW, I don't think that's a correct interpretation. The manual page > clearly says after close(2), even on error, the fd is closed and not > usable. The issue I see is a program thinking it failed and trying to > copy the file again or reporting an error. The authoritative source here is POSIX not the man page, assuming you're writing a portable application and not a "Linux application". Until the lastest issue (POSIX 2024/Issue 8), the state of the fd after EINTR was explicitly unspecified, and after other errors was unspecified by omission. So there is no way for a program written to prior versions of the standard to have known how to safely handle getting EINPROGRESS -- or any error from close for that matter. Really, the only safe error for close to return, *ever*, is EBADF. On valid input, it *must succeed*. This is a general principle for "deallocation/destruction functions". Not an explicit requirement of this or any standard; just a logical requirement for forward progress to be possible. > On the other hand, as Vincent said, maybe this is not so bad. For > certain files, fsync(2) is only described for storage devices, so in > some cases there's no clear way to make sure close(2) won't fail after > EINTR (maybe calling sync(2)?). So, maybe considering it an error > wouldn't be a terrible idea. Whether data is committed to physical storage in a way that's robust against machine faults is a completely separate issue from whether it's committed to the abstract storage. The latter happens at the moment of write, not close. If an application is trying to ensure that kind of robustness, the return value of close is not the tool. It needs the Synchronized IO interfaces (fsync, etc.) or something specific to whatever it's writing to. Rich ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 13:05 ` Rich Felker 2025-05-16 14:20 ` Theodore Ts'o @ 2025-05-16 14:39 ` Vincent Lefevre 2025-05-16 14:52 ` Florian Weimer ` (2 more replies) 1 sibling, 3 replies; 25+ messages in thread From: Vincent Lefevre @ 2025-05-16 14:39 UTC (permalink / raw) To: Rich Felker Cc: Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On 2025-05-16 09:05:47 -0400, Rich Felker wrote: > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > issue, and later changed it to returning 0 since applications > (particularly, any written prior to this interpretation) are prone to > interpret EINPROGRESS as an error condition rather than success and > possibly misinterpret it as meaning the fd is still open and valid to > pass to close again. If I understand correctly, this is a poor choice. POSIX.1-2024 says: ERRORS The close() and posix_close() functions shall fail if: [...] [EINPROGRESS] The function was interrupted by a signal and fildes was closed but the close operation is continuing asynchronously. But this does not mean that the asynchronous close operation will succeed. So the application could incorrectly deduce that the close operation was done without any error. -- Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/> Work: CR INRIA - computer arithmetic / Pascaline project (LIP, ENS-Lyon) ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 14:39 ` Vincent Lefevre @ 2025-05-16 14:52 ` Florian Weimer 2025-05-16 15:28 ` Vincent Lefevre 2025-05-16 15:28 ` Rich Felker 2025-05-17 13:32 ` Rich Felker 2 siblings, 1 reply; 25+ messages in thread From: Florian Weimer @ 2025-05-16 14:52 UTC (permalink / raw) To: Vincent Lefevre Cc: Rich Felker, Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha * Vincent Lefevre: > On 2025-05-16 09:05:47 -0400, Rich Felker wrote: >> FWIW musl adopted the EINPROGRESS as soon as we were made aware of the >> issue, and later changed it to returning 0 since applications >> (particularly, any written prior to this interpretation) are prone to >> interpret EINPROGRESS as an error condition rather than success and >> possibly misinterpret it as meaning the fd is still open and valid to >> pass to close again. > > If I understand correctly, this is a poor choice. POSIX.1-2024 says: > > ERRORS > The close() and posix_close() functions shall fail if: > [...] > [EINPROGRESS] > The function was interrupted by a signal and fildes was closed > but the close operation is continuing asynchronously. > > But this does not mean that the asynchronous close operation will > succeed. > > So the application could incorrectly deduce that the close operation > was done without any error. But on Linux, close traditionally has poor error reporting anyway. You have to fsync (or equivalent) before calling close if you want error checking. On other systems, the fsync is more or less implied by the close, leading to rather poor performance. Thanks, Florian ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 14:52 ` Florian Weimer @ 2025-05-16 15:28 ` Vincent Lefevre 0 siblings, 0 replies; 25+ messages in thread From: Vincent Lefevre @ 2025-05-16 15:28 UTC (permalink / raw) To: Florian Weimer Cc: Rich Felker, Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On 2025-05-16 16:52:48 +0200, Florian Weimer wrote: > * Vincent Lefevre: > > > On 2025-05-16 09:05:47 -0400, Rich Felker wrote: > >> FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > >> issue, and later changed it to returning 0 since applications > >> (particularly, any written prior to this interpretation) are prone to > >> interpret EINPROGRESS as an error condition rather than success and > >> possibly misinterpret it as meaning the fd is still open and valid to > >> pass to close again. > > > > If I understand correctly, this is a poor choice. POSIX.1-2024 says: > > > > ERRORS > > The close() and posix_close() functions shall fail if: > > [...] > > [EINPROGRESS] > > The function was interrupted by a signal and fildes was closed > > but the close operation is continuing asynchronously. > > > > But this does not mean that the asynchronous close operation will > > succeed. > > > > So the application could incorrectly deduce that the close operation > > was done without any error. > > But on Linux, close traditionally has poor error reporting anyway. You > have to fsync (or equivalent) before calling close if you want error > checking. On other systems, the fsync is more or less implied by the > close, leading to rather poor performance. According to its documentation, fsync is only for storage devices, while not all file descriptors are associated with storage devices. So I'm wondering the consequences in the other cases. -- Vincent Lefèvre <vincent@vinc17.net> - Web: <https://www.vinc17.net/> 100% accessible validated (X)HTML - Blog: <https://www.vinc17.net/blog/> Work: CR INRIA - computer arithmetic / Pascaline project (LIP, ENS-Lyon) ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 14:39 ` Vincent Lefevre 2025-05-16 14:52 ` Florian Weimer @ 2025-05-16 15:28 ` Rich Felker 2025-05-17 13:32 ` Rich Felker 2 siblings, 0 replies; 25+ messages in thread From: Rich Felker @ 2025-05-16 15:28 UTC (permalink / raw) To: Vincent Lefevre, Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On Fri, May 16, 2025 at 04:39:57PM +0200, Vincent Lefevre wrote: > On 2025-05-16 09:05:47 -0400, Rich Felker wrote: > > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > > issue, and later changed it to returning 0 since applications > > (particularly, any written prior to this interpretation) are prone to > > interpret EINPROGRESS as an error condition rather than success and > > possibly misinterpret it as meaning the fd is still open and valid to > > pass to close again. > > If I understand correctly, this is a poor choice. POSIX.1-2024 says: > > ERRORS > The close() and posix_close() functions shall fail if: > [...] > [EINPROGRESS] > The function was interrupted by a signal and fildes was closed > but the close operation is continuing asynchronously. > > But this does not mean that the asynchronous close operation will > succeed. It always succeeds in the way that's important: the file descriptor is freed and the process no longer has this reference to the open file description. What might or might not succeed is: (1) other ancient legacy behaviors coupled to close(), like rewinding a tape drive. If the application cares how that behaves, it needs to be performing an explicit rewind *before* calling close, when it still has a handle on the open file so that it can respond to exceptional conditions, not relying on a legacy behavior like "close also rewinds" that's device-specific and outside the scope of any modern cross-platform standard. (2) deferred operations in unsafe async NFS setups. This is a huge mess with no real reliable solution except "don't configure your NFS to have unsafe and nonconforming behaviors in the pursuit of performance". Rich ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-16 14:39 ` Vincent Lefevre 2025-05-16 14:52 ` Florian Weimer 2025-05-16 15:28 ` Rich Felker @ 2025-05-17 13:32 ` Rich Felker 2025-05-17 13:46 ` Alejandro Colomar 2 siblings, 1 reply; 25+ messages in thread From: Rich Felker @ 2025-05-17 13:32 UTC (permalink / raw) To: Vincent Lefevre, Alejandro Colomar, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha On Fri, May 16, 2025 at 04:39:57PM +0200, Vincent Lefevre wrote: > On 2025-05-16 09:05:47 -0400, Rich Felker wrote: > > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > > issue, and later changed it to returning 0 since applications > > (particularly, any written prior to this interpretation) are prone to > > interpret EINPROGRESS as an error condition rather than success and > > possibly misinterpret it as meaning the fd is still open and valid to > > pass to close again. > > If I understand correctly, this is a poor choice. POSIX.1-2024 says: > > ERRORS > The close() and posix_close() functions shall fail if: > [...] > [EINPROGRESS] > The function was interrupted by a signal and fildes was closed > but the close operation is continuing asynchronously. > > But this does not mean that the asynchronous close operation will > succeed. There are no asynchronous behaviors specified for there to be a conformance distinction here. The only observable behaviors happen instantly, mainly the release of the file descriptor and the process's handle on the underlying resource. Abstractly, there is no async operation that could succeed or fail. > So the application could incorrectly deduce that the close operation > was done without any error. This deduction is correct, not incorrect. Rather, failing with EINPROGRESS would make the application incorrectly deduce that there might be some error it missed (even if it's aware of the new error code), and absolutely does make all existing applications written prior to the new text in POSIX 2024 unable to determine if the fd was even released and needs to be passed to close again or not. Rich ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-17 13:32 ` Rich Felker @ 2025-05-17 13:46 ` Alejandro Colomar 2025-05-23 18:10 ` Zack Weinberg 0 siblings, 1 reply; 25+ messages in thread From: Alejandro Colomar @ 2025-05-17 13:46 UTC (permalink / raw) To: Rich Felker Cc: Vincent Lefevre, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, libc-alpha [-- Attachment #1: Type: text/plain, Size: 3465 bytes --] On Sat, May 17, 2025 at 09:32:52AM -0400, Rich Felker wrote: > On Fri, May 16, 2025 at 04:39:57PM +0200, Vincent Lefevre wrote: > > On 2025-05-16 09:05:47 -0400, Rich Felker wrote: > > > FWIW musl adopted the EINPROGRESS as soon as we were made aware of the > > > issue, and later changed it to returning 0 since applications > > > (particularly, any written prior to this interpretation) are prone to > > > interpret EINPROGRESS as an error condition rather than success and > > > possibly misinterpret it as meaning the fd is still open and valid to > > > pass to close again. > > > > If I understand correctly, this is a poor choice. POSIX.1-2024 says: > > > > ERRORS > > The close() and posix_close() functions shall fail if: > > [...] > > [EINPROGRESS] > > The function was interrupted by a signal and fildes was closed > > but the close operation is continuing asynchronously. > > > > But this does not mean that the asynchronous close operation will > > succeed. > > There are no asynchronous behaviors specified for there to be a > conformance distinction here. The only observable behaviors happen > instantly, mainly the release of the file descriptor and the process's > handle on the underlying resource. Abstractly, there is no async > operation that could succeed or fail. > > > So the application could incorrectly deduce that the close operation > > was done without any error. > > This deduction is correct, not incorrect. Rather, failing with > EINPROGRESS would make the application incorrectly deduce that there > might be some error it missed (even if it's aware of the new error > code), and absolutely does make all existing applications written > prior to the new text in POSIX 2024 unable to determine if the fd was > even released and needs to be passed to close again or not. Hi Rich, I think this is not correct; at least on Linux. The manual page is very clear that close(2) should not be retried on error: Dealing with error returns from close() A careful programmer will check the return value of close(), since it is quite possible that errors on a previous write(2) operation are reported only on the final close() that releases the open file description. Failing to check the return value when closing a file may lead to silent loss of data. This can especially be observed with NFS and with disk quota. Note, however, that a failure return should be used only for di‐ agnostic purposes (i.e., a warning to the application that there may still be I/O pending or there may have been failed I/O) or remedial purposes (e.g., writing the file once more or creating a backup). Retrying the close() after a failure return is the wrong thing to do, since this may cause a reused file descriptor from an‐ other thread to be closed. This can occur because the Linux kernel always releases the file descriptor early in the close operation, freeing it for reuse; the steps that may return an error, such as flushing data to the filesystem or device, occur only later in the close operation. ... A careful programmer who wants to know about I/O errors may pre‐ cede close() with a call to fsync(2). Cheers, Alex -- <https://www.alejandro-colomar.es/> [-- Attachment #2: signature.asc --] [-- Type: application/pgp-signature, Size: 833 bytes --] ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-17 13:46 ` Alejandro Colomar @ 2025-05-23 18:10 ` Zack Weinberg 2025-05-24 2:24 ` Rich Felker 2025-05-24 19:25 ` Florian Weimer 0 siblings, 2 replies; 25+ messages in thread From: Zack Weinberg @ 2025-05-23 18:10 UTC (permalink / raw) To: Alejandro Colomar, Rich Felker Cc: Vincent Lefevre, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, GNU libc development Taking everything said in this thread into account, I have attempted to wordsmith new language for the close(2) manpage. Please let me know what you think, and please help me with the bits marked in square brackets. I can make this into a proper patch for the manpages when everyone is happy with it. zw --- DESCRIPTION ... existing text ... close() always succeeds. That is, after it returns, _fd_ has always been disconnected from the open file it formerly referred to, and its number can be recycled to refer to some other file. Furthermore, if _fd_ was the last reference to the underlying open file description, the resources associated with the open file description will always have been scheduled to be released. However, close may report _delayed errors_ from a previous I/O operation. Therefore, its return value should not be ignored. RETURN VALUE close() returns zero if there are no delayed errors to report, or -1 if there _might_ be delayed errors. When close() returns -1, check _errno_ to see what the situation actually is. Most, but not all, _errno_ codes indicate a delayed I/O error that should be reported to the user. See ERRORS and NOTES for more detail. [QUERY: Is it ever possible to get delayed errors on close() from a file that was opened with O_RDONLY? What about a file that was opened with O_RDWR but never actually written to? If people only have to worry about delayed errors if the file was actually written to, we should say so at this point. It would also be good to mention whether it is possible to get a delayed error on close() even if a previous call to fsync() or fdatasync() succeeded and there haven’t been any more writes to that file *description* (not necessarily via the fd being closed) since.] ERRORS EBADF _fd_ wasn’t open in the first place, or is outside the valid numeric range for file descriptors. EINPROGRESS EINTR There are no delayed errors to report, but the kernel is still doing some clean-up work in the background. This situation should be treated the same as if close() had returned zero. Do not retry the close(), and do not report an error to the user. EDQUOT EFBIG EIO ENOSPC These are the most common errno codes associated with delayed I/O errors. They should be treated as a hard failure to write to the file that was formerly associated with _fd_, the same as if an earlier write(2) had failed with one of these codes. The file has still been closed! Do not retry the close(). But do report an error to the user. Depending on the underlying file, close() may return other errno codes; these should generally also be treated as delayed I/O errors. NOTES Dealing with error returns from close() As discussed above, close() always closes the file. Except when errno is set to EBADF, EINPROGRESS, or EINTR, an error return from close() reports a _delayed I/O error_ from a previous write() operation. It is vital to report delayed I/O errors to the user; failing to check the return value of close() can cause _silent_ loss of data. The most common situations where this actually happens involve networked filesystems, where, in the name of throughput, write() often returns success before the server has actually confirmed a successful write. However, it is also vital to understand that _no matter what_ close() returns, and _no matter what_ it sets errno to, when it returns, _the file descriptor passed to close() has been closed_, and its number is _immediately_ available for reuse by open(2), dup(2), etc. Therefore, one should never retry a close(), not even if it set errno to a value that normally indicates the operation needs to be retried (e.g. EINTR). Retrying a close() is a serious bug, particularly in a multithreaded program; if the file descriptor number has already been reused, _that file_ will get closed out from under whatever other thread opened it. [Possibly something about fsync/fdatasync here?] BUGS Prior to POSIX.1-2024, there was no official guarantee that close() would always close the file descriptor, even on error. Linux has always closed the file descriptor, even on error, but other implementations might not have. The only such implementation we have heard of is HP-UX; at least some versions of HP-UX’s man page for close() said it should be retried if it returned -1 with errno set to EINTR. (If you know exactly which versions of HP-UX are affected, or of any other Unix where close() doesn’t always close the file descriptor, please contact us about it.) Portable code should nonetheless never retry a failed close(); the consequences of a file descriptor leak are far less dangerous than the consequences of closing a file out from under another thread. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-23 18:10 ` Zack Weinberg @ 2025-05-24 2:24 ` Rich Felker 2025-05-24 19:25 ` Florian Weimer 1 sibling, 0 replies; 25+ messages in thread From: Rich Felker @ 2025-05-24 2:24 UTC (permalink / raw) To: Zack Weinberg Cc: Alejandro Colomar, Vincent Lefevre, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, GNU libc development On Fri, May 23, 2025 at 02:10:57PM -0400, Zack Weinberg wrote: > Taking everything said in this thread into account, I have attempted to > wordsmith new language for the close(2) manpage. Please let me know > what you think, and please help me with the bits marked in square > brackets. I can make this into a proper patch for the manpages > when everyone is happy with it. > > zw > > --- > > DESCRIPTION > ... existing text ... > > close() always succeeds. That is, after it returns, _fd_ has > always been disconnected from the open file it formerly referred > to, and its number can be recycled to refer to some other file. > Furthermore, if _fd_ was the last reference to the underlying > open file description, the resources associated with the open file > description will always have been scheduled to be released. > > However, close may report _delayed errors_ from a previous I/O > operation. Therefore, its return value should not be ignored. > > RETURN VALUE > close() returns zero if there are no delayed errors to report, > or -1 if there _might_ be delayed errors. > > When close() returns -1, check _errno_ to see what the situation > actually is. Most, but not all, _errno_ codes indicate a delayed > I/O error that should be reported to the user. See ERRORS and > NOTES for more detail. > > [QUERY: Is it ever possible to get delayed errors on close() from > a file that was opened with O_RDONLY? What about a file that was > opened with O_RDWR but never actually written to? If people only > have to worry about delayed errors if the file was actually > written to, we should say so at this point. > > It would also be good to mention whether it is possible to get a > delayed error on close() even if a previous call to fsync() or > fdatasync() succeeded and there haven’t been any more writes to > that file *description* (not necessarily via the fd being closed) > since.] > > ERRORS > EBADF _fd_ wasn’t open in the first place, or is outside the > valid numeric range for file descriptors. > > EINPROGRESS > EINTR > There are no delayed errors to report, but the kernel is > still doing some clean-up work in the background. This > situation should be treated the same as if close() had > returned zero. Do not retry the close(), and do not report > an error to the user. Since this behavior for EINTR is non-conforming (and even prior to the POSIX 2024 update, it was contrary to the general semantics for EINTR, that no non-ignoreable side-effects have taken place), it should be noted that it's Linux/glibc-specific. > EDQUOT > EFBIG > EIO > ENOSPC > These are the most common errno codes associated with > delayed I/O errors. They should be treated as a hard > failure to write to the file that was formerly associated > with _fd_, the same as if an earlier write(2) had failed > with one of these codes. The file has still been closed! > Do not retry the close(). But do report an error to the user. > > Depending on the underlying file, close() may return other errno > codes; these should generally also be treated as delayed I/O errors. > > NOTES > Dealing with error returns from close() > > As discussed above, close() always closes the file. Except when > errno is set to EBADF, EINPROGRESS, or EINTR, an error return from > close() reports a _delayed I/O error_ from a previous write() > operation. > > It is vital to report delayed I/O errors to the user; failing to > check the return value of close() can cause _silent_ loss of data. > The most common situations where this actually happens involve > networked filesystems, where, in the name of throughput, write() > often returns success before the server has actually confirmed a > successful write. > > However, it is also vital to understand that _no matter what_ > close() returns, and _no matter what_ it sets errno to, when it > returns, _the file descriptor passed to close() has been closed_, > and its number is _immediately_ available for reuse by open(2), > dup(2), etc. Therefore, one should never retry a close(), not > even if it set errno to a value that normally indicates the > operation needs to be retried (e.g. EINTR). Retrying a close() > is a serious bug, particularly in a multithreaded program; if > the file descriptor number has already been reused, _that file_ > will get closed out from under whatever other thread opened it. > > [Possibly something about fsync/fdatasync here?] While I agree with all of this, I think the tone is way too proscriptive. The man pages are to document the behaviors, not tell people how to program. And again, it should be noted that the standard behavior is that you *do* have to retry on EINTR, or arrange to ensure it never happens (e.g. by not installing interrupting signal handlers, or blocking signals across calls to close), and that treating EINTR as "fd has been closed" is something you should only do on known-nonconforming systems. Aside: the reason EINTR *has to* be specified this way is that pthread cancellation is aligned with EINTR. If EINTR were defined to have closed the fd, then acting on cancellation during close would also have closed the fd, but the cancellation handler would have no way to distinguish this, leading to a situation where you're forced to either leak fds or introduce a double-close vuln. > BUGS > Prior to POSIX.1-2024, there was no official guarantee that > close() would always close the file descriptor, even on error. > Linux has always closed the file descriptor, even on error, > but other implementations might not have. > > The only such implementation we have heard of is HP-UX; at least > some versions of HP-UX’s man page for close() said it should be > retried if it returned -1 with errno set to EINTR. (If you know > exactly which versions of HP-UX are affected, or of any other > Unix where close() doesn’t always close the file descriptor, > please contact us about it.) > > Portable code should nonetheless never retry a failed close(); the > consequences of a file descriptor leak are far less dangerous than > the consequences of closing a file out from under another thread. This is explicitly the opposite of what's specified for portable code. It sounds like you are intentionally omitting that POSIX says the opposite of what you want it to, and treating the standard behavior as a historical HP-UX quirk/bug. This is polemic, not the sort of documentation that belongs in a man page. An outline of what I'd like to see instead: - Clear explanation of why double-close is a serious bug that must always be avoided. (I think we all agree on this.) - Statement that the historical Linux/glibc behavior and current POSIX requirement differ, without language that tries to paint the POSIX behavior as a HP-UX bug/quirk. Possibly citing real sources/history of the issue (Austin Group tracker items 529, 614; maybe others). - Consequence of just assuming the Linux behavior (fd leaks on conforming systems). - Consequences of assuming the POSIX behavior (double-close vulns on GNU/Linux, maybe others). - Survey of methods for avoiding the problem (ways to preclude EINTR, possibly ways to infer behavior, etc). Rich ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 2025-05-23 18:10 ` Zack Weinberg 2025-05-24 2:24 ` Rich Felker @ 2025-05-24 19:25 ` Florian Weimer 1 sibling, 0 replies; 25+ messages in thread From: Florian Weimer @ 2025-05-24 19:25 UTC (permalink / raw) To: Zack Weinberg Cc: Alejandro Colomar, Rich Felker, Vincent Lefevre, Jan Kara, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, GNU libc development * Zack Weinberg: > BUGS > Prior to POSIX.1-2024, there was no official guarantee that > close() would always close the file descriptor, even on error. > Linux has always closed the file descriptor, even on error, > but other implementations might not have. > > The only such implementation we have heard of is HP-UX; at least > some versions of HP-UX’s man page for close() said it should be > retried if it returned -1 with errno set to EINTR. (If you know > exactly which versions of HP-UX are affected, or of any other > Unix where close() doesn’t always close the file descriptor, > please contact us about it.) The AIX documentation also says this: | The success of the close subroutine is undetermined if the following | is true: | | EINTR The state of the FileDescriptor is undetermined. Retry the | close routine to ensure that the FileDescriptor is closed. <https://www.ibm.com/docs/en/aix/7.2.0?topic=c-close-subroutine> So it's not just HP-UX. For z/OS, it looks like some other errors leave the descriptor open: | EAGAIN | | The call did not complete because the specified socket descriptor | is currently being used by another thread in the same process. | | For example, in a multithreaded environment, close() fails and | returns EAGAIN when the following sequence of events occurs (1) | thread is blocked in a read() or select() call on a given file or | socket descriptor and (2) another thread issues a simultaneous | close() call for the same descriptor. | […] | EBADF | fildes is not a valid open file descriptor, or the socket | parameter is not a valid socket descriptor. <https://www.ibm.com/docs/en/zos/2.1.0?topic=functions-close-close-file> ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-16 10:48 ` Jan Kara 2025-05-16 12:11 ` Alejandro Colomar @ 2025-05-16 12:41 ` Mateusz Guzik 2025-05-16 12:41 ` Theodore Ts'o ` (2 subsequent siblings) 4 siblings, 0 replies; 25+ messages in thread From: Mateusz Guzik @ 2025-05-16 12:41 UTC (permalink / raw) To: Jan Kara Cc: Alejandro Colomar, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, linux-man On Fri, May 16, 2025 at 12:48:56PM +0200, Jan Kara wrote: > Hi! > > On Thu 15-05-25 23:33:22, Alejandro Colomar wrote: > > I'm updating the manual pages for POSIX.1-2024, and have some doubts > > about close(2). The manual page for close(2) says (conforming to > > POSIX.1-2008): > > > > The EINTR error is a somewhat special case. Regarding the EINTR > > error, POSIX.1‐2008 says: > > > > If close() is interrupted by a signal that is to be > > caught, it shall return -1 with errno set to EINTR and > > the state of fildes is unspecified. > > > > This permits the behavior that occurs on Linux and many other > > implementations, where, as with other errors that may be re‐ > > ported by close(), the file descriptor is guaranteed to be > > closed. However, it also permits another possibility: that the > > implementation returns an EINTR error and keeps the file de‐ > > scriptor open. (According to its documentation, HP‐UX’s close() > > does this.) The caller must then once more use close() to close > > the file descriptor, to avoid file descriptor leaks. This di‐ > > vergence in implementation behaviors provides a difficult hurdle > > for portable applications, since on many implementations, > > close() must not be called again after an EINTR error, and on at > > least one, close() must be called again. There are plans to ad‐ > > dress this conundrum for the next major release of the POSIX.1 > > standard. > > > > TL;DR: close(2) with EINTR is allowed to either leave the fd open or > > closed, and Linux leaves it closed, while others (HP-UX only?) leaves it > > open. > > > > Now, POSIX.1-2024 says: > > > > If close() is interrupted by a signal that is to be caught, then > > it is unspecified whether it returns -1 with errno set to > > [EINTR] and fildes remaining open, or returns -1 with errno set > > to [EINPROGRESS] and fildes being closed, or returns 0 to > > indicate successful completion; [...] > > > > <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> > > > > Which seems to bless HP-UX and screw all the others, requiring them to > > report EINPROGRESS. > > > > Was there any discussion about what to do in the Linux kernel? > > I'm not aware of any discussions but indeed we are returning EINTR while > closing the fd. Frankly, changing the error code we return in that case is > really asking for userspace regressions so I'm of the opinion we just > ignore the standard as in my opinion it goes against a long established > reality. I wonder what are they thinking there. Any program which even bothers to check for EINTR assumes the fd is already closed, so one has to assume augmenting behavior to support this would result in fd leaks. But that crappery aside, I do wonder if a close() variant which can fail and leaves the fd intact would be warranted. For example one of the error modes is ENOSPC (or at least the manpage claims as much). As is the error is not actionable as the fd is gone. If instead a magic flag was passed down to indicate what to do (e.g., leave the fd in place), the program could try to do some recovery (for examples unlinking temp files it knows it stores there). Similar deal with EINTR, albeit this error for close() would preferably get eradicated instead. Just some meh rambling. ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-16 10:48 ` Jan Kara 2025-05-16 12:11 ` Alejandro Colomar 2025-05-16 12:41 ` close(2) with EINTR has been changed by POSIX.1-2024 Mateusz Guzik @ 2025-05-16 12:41 ` Theodore Ts'o 2025-05-19 23:19 ` Steffen Nurpmeso 2025-05-16 19:13 ` Al Viro 2025-05-19 9:48 ` Christian Brauner 4 siblings, 1 reply; 25+ messages in thread From: Theodore Ts'o @ 2025-05-16 12:41 UTC (permalink / raw) To: Jan Kara Cc: Alejandro Colomar, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, linux-man On Fri, May 16, 2025 at 12:48:56PM +0200, Jan Kara wrote: > > Now, POSIX.1-2024 says: > > > > If close() is interrupted by a signal that is to be caught, then > > it is unspecified whether it returns -1 with errno set to > > [EINTR] and fildes remaining open, or returns -1 with errno set > > to [EINPROGRESS] and fildes being closed, or returns 0 to > > indicate successful completion; [...] > > > > <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> > > > > Which seems to bless HP-UX and screw all the others, requiring them to > > report EINPROGRESS. > > > > Was there any discussion about what to do in the Linux kernel? > > I'm not aware of any discussions but indeed we are returning EINTR while > closing the fd. Frankly, changing the error code we return in that case is > really asking for userspace regressions so I'm of the opinion we just > ignore the standard as in my opinion it goes against a long established > reality. Yeah, it appears that the Austin Group has lost all connection with reality, and we should treat POSIX 2024 accordingly. Not breaking userspace applications is way more important that POSIX 2024 compliance. Which is sad, because I used to really care about POSIX.1 standard as being very useful. But that seems to be no longer the case... - Ted ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-16 12:41 ` Theodore Ts'o @ 2025-05-19 23:19 ` Steffen Nurpmeso 2025-05-20 13:37 ` Theodore Ts'o 0 siblings, 1 reply; 25+ messages in thread From: Steffen Nurpmeso @ 2025-05-19 23:19 UTC (permalink / raw) To: Theodore Ts'o Cc: Jan Kara, Alejandro Colomar, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, linux-man, Steffen Nurpmeso Theodore Ts'o wrote in <20250516124147.GB7158@mit.edu>: |On Fri, May 16, 2025 at 12:48:56PM +0200, Jan Kara wrote: |>> Now, POSIX.1-2024 says: |>> |>> If close() is interrupted by a signal that is to be caught, then |>> it is unspecified whether it returns -1 with errno set to |>> [EINTR] and fildes remaining open, or returns -1 with errno set |>> to [EINPROGRESS] and fildes being closed, or returns 0 to |>> indicate successful completion; [...] |>> |>> <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> |>> |>> Which seems to bless HP-UX and screw all the others, requiring them to |>> report EINPROGRESS. |>> |>> Was there any discussion about what to do in the Linux kernel? |> |> I'm not aware of any discussions but indeed we are returning EINTR while |> closing the fd. Frankly, changing the error code we return in that \ |> case is |> really asking for userspace regressions so I'm of the opinion we just |> ignore the standard as in my opinion it goes against a long established |> reality. | |Yeah, it appears that the Austin Group has lost all connection with |reality, and we should treat POSIX 2024 accordingly. Not breaking |userspace applications is way more important that POSIX 2024 |compliance. Which is sad, because I used to really care about POSIX.1 |standard as being very useful. But that seems to be no longer the |case... They could not do otherwise than talking the status quo, i think. They have explicitly added posix_close() which overcomes the problem (for those operating systems which actually act like that). There is a long RATIONALE on this, it starts on page 747 :) --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-19 23:19 ` Steffen Nurpmeso @ 2025-05-20 13:37 ` Theodore Ts'o 2025-05-20 23:16 ` Steffen Nurpmeso 0 siblings, 1 reply; 25+ messages in thread From: Theodore Ts'o @ 2025-05-20 13:37 UTC (permalink / raw) To: Jan Kara, Alejandro Colomar, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, linux-man, Steffen Nurpmeso On Tue, May 20, 2025 at 01:19:19AM +0200, Steffen Nurpmeso wrote: > > They could not do otherwise than talking the status quo, i think. > They have explicitly added posix_close() which overcomes the > problem (for those operating systems which actually act like > that). There is a long RATIONALE on this, it starts on page 747 :) They could have just added posix_close() which provided well-defined semantics without demanding that existing implementations make non-backwards compatible changes to close(2). Personally, while they were adding posix_close(2) they could have also fixed the disaster which is the semantics around close(2) and how advisory locks get released that were held by other file descriptors and add a profound apologies over the insane semantics demanded by POSIX[1]. [1] "POSIX advisory locks are broken by design." https://www.sqlite.org/src/artifact/c230a7a24?ln=994-1081 - Ted ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-20 13:37 ` Theodore Ts'o @ 2025-05-20 23:16 ` Steffen Nurpmeso 0 siblings, 0 replies; 25+ messages in thread From: Steffen Nurpmeso @ 2025-05-20 23:16 UTC (permalink / raw) To: Theodore Ts'o Cc: Jan Kara, Alejandro Colomar, Alexander Viro, Christian Brauner, linux-fsdevel, linux-api, linux-man, Steffen Nurpmeso Theodore Ts'o wrote in <20250520133705.GE38098@mit.edu>: |On Tue, May 20, 2025 at 01:19:19AM +0200, Steffen Nurpmeso wrote: |> They could not do otherwise than talking the status quo, i think. |> They have explicitly added posix_close() which overcomes the |> problem (for those operating systems which actually act like |> that). There is a long RATIONALE on this, it starts on page 747 :) | |They could have just added posix_close() which provided well-defined |semantics without demanding that existing implementations make |non-backwards compatible changes to close(2). Personally, while they |were adding posix_close(2) they could have also fixed the disaster |which is the semantics around close(2) [.] Well it was a lot of trouble, not only in bug 529[1], with follow-ups like a thread started by Michael Kerrisk, with an interesting response by Rich Felker of Musl[2]. In [1] Erik Blake of RedHat/libvirt said for example The Linux kernel currently always frees the file descriptor (no chance for a retry; the filedes can immediately be reused by another open()), for both EINTR and EIO. Maybe it is safer to state that the fd is _always_ closed, even if failure is reported? etc, but Geoff Clare then (this also was in 2012, where one possibly could have hoped that more operating systems survive / continue with money/manpower backing by serious companies; just in case that mattered) came via HP got it right with HP-UX; AIX and Linux do the wrong thing. and he has quite some reasoning for descriptors like ttys etc, where close can linger, which resulted in Erik Blake quoting Let me make it very, very clear - no matter how many times these guys assert HP-UX insane behaviour correct, no "fixes" to Linux one are going to be accepted. Consider it vetoed. By me, in role of Linux VFS maintainer. And I'm _very_ certain that getting Linus to agree will be a matter of minutes. [1] https://www.austingroupbugs.net/view.php?id=529 [2] https://www.mail-archive.com/austin-group-l@opengroup.org/msg00579.html |[.] and how advisory locks get |released that were held by other file descriptors and add a profound |apologies over the insane semantics demanded by POSIX[1]. The new standard added the Linux-style F_OFD_* fcntl(2) locks! They are yet Linux-only, but NetBSD at least has an issue by a major contributor (bug 59241): NetBSD seems to lack the following: 3.237 OFD-Owned File Lock ... https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap03.html#tag_03_237 >How-To-Repeat: standards inspection >Fix: Yes, please! (That or write down a reason why we eschew it.) |[1] "POSIX advisory locks are broken by design." | https://www.sqlite.org/src/artifact/c230a7a24?ln=994-1081 | | - Ted --End of <20250520133705.GE38098@mit.edu> --steffen | |Der Kragenbaer, The moon bear, |der holt sich munter he cheerfully and one by one |einen nach dem anderen runter wa.ks himself off |(By Robert Gernhardt) ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-16 10:48 ` Jan Kara ` (2 preceding siblings ...) 2025-05-16 12:41 ` Theodore Ts'o @ 2025-05-16 19:13 ` Al Viro 2025-05-19 9:48 ` Christian Brauner 4 siblings, 0 replies; 25+ messages in thread From: Al Viro @ 2025-05-16 19:13 UTC (permalink / raw) To: Jan Kara Cc: Alejandro Colomar, Christian Brauner, linux-fsdevel, linux-api, linux-man On Fri, May 16, 2025 at 12:48:56PM +0200, Jan Kara wrote: > I'm not aware of any discussions but indeed we are returning EINTR while > closing the fd. Frankly, changing the error code we return in that case is > really asking for userspace regressions so I'm of the opinion we just > ignore the standard as in my opinion it goes against a long established > reality. AFAICS what happens is that relevance of Austin Group has dropped so low that they stopped caring about any BS filters they used to have. What we are seeing now is assorted pet idiocies that used to sit in their system, periodically getting shot down while there had been anyone who cared to do that. Sad, of course, but what can we do, other than politely ignoring the... output? ^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: close(2) with EINTR has been changed by POSIX.1-2024 2025-05-16 10:48 ` Jan Kara ` (3 preceding siblings ...) 2025-05-16 19:13 ` Al Viro @ 2025-05-19 9:48 ` Christian Brauner 4 siblings, 0 replies; 25+ messages in thread From: Christian Brauner @ 2025-05-19 9:48 UTC (permalink / raw) To: Jan Kara Cc: Alejandro Colomar, Alexander Viro, linux-fsdevel, linux-api, linux-man On Fri, May 16, 2025 at 12:48:56PM +0200, Jan Kara wrote: > Hi! > > On Thu 15-05-25 23:33:22, Alejandro Colomar wrote: > > I'm updating the manual pages for POSIX.1-2024, and have some doubts > > about close(2). The manual page for close(2) says (conforming to > > POSIX.1-2008): > > > > The EINTR error is a somewhat special case. Regarding the EINTR > > error, POSIX.1‐2008 says: > > > > If close() is interrupted by a signal that is to be > > caught, it shall return -1 with errno set to EINTR and > > the state of fildes is unspecified. > > > > This permits the behavior that occurs on Linux and many other > > implementations, where, as with other errors that may be re‐ > > ported by close(), the file descriptor is guaranteed to be > > closed. However, it also permits another possibility: that the > > implementation returns an EINTR error and keeps the file de‐ > > scriptor open. (According to its documentation, HP‐UX’s close() > > does this.) The caller must then once more use close() to close > > the file descriptor, to avoid file descriptor leaks. This di‐ > > vergence in implementation behaviors provides a difficult hurdle > > for portable applications, since on many implementations, > > close() must not be called again after an EINTR error, and on at > > least one, close() must be called again. There are plans to ad‐ > > dress this conundrum for the next major release of the POSIX.1 > > standard. > > > > TL;DR: close(2) with EINTR is allowed to either leave the fd open or > > closed, and Linux leaves it closed, while others (HP-UX only?) leaves it > > open. > > > > Now, POSIX.1-2024 says: > > > > If close() is interrupted by a signal that is to be caught, then > > it is unspecified whether it returns -1 with errno set to > > [EINTR] and fildes remaining open, or returns -1 with errno set > > to [EINPROGRESS] and fildes being closed, or returns 0 to > > indicate successful completion; [...] > > > > <https://pubs.opengroup.org/onlinepubs/9799919799/functions/close.html> > > > > Which seems to bless HP-UX and screw all the others, requiring them to > > report EINPROGRESS. > > > > Was there any discussion about what to do in the Linux kernel? > > I'm not aware of any discussions but indeed we are returning EINTR while > closing the fd. Frankly, changing the error code we return in that case is > really asking for userspace regressions so I'm of the opinion we just > ignore the standard as in my opinion it goes against a long established > reality. Ignore. We've long since stopped designing apis with input from that standard in mind. And I think that was a very wise decision. ^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2025-05-24 19:31 UTC | newest] Thread overview: 25+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-05-15 21:33 close(2) with EINTR has been changed by POSIX.1-2024 Alejandro Colomar 2025-05-16 10:48 ` Jan Kara 2025-05-16 12:11 ` Alejandro Colomar 2025-05-16 12:52 ` [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024 Alejandro Colomar 2025-05-16 13:05 ` Rich Felker 2025-05-16 14:20 ` Theodore Ts'o 2025-05-17 5:46 ` Alejandro Colomar 2025-05-17 13:03 ` Alejandro Colomar 2025-05-17 13:43 ` Rich Felker 2025-05-16 14:39 ` Vincent Lefevre 2025-05-16 14:52 ` Florian Weimer 2025-05-16 15:28 ` Vincent Lefevre 2025-05-16 15:28 ` Rich Felker 2025-05-17 13:32 ` Rich Felker 2025-05-17 13:46 ` Alejandro Colomar 2025-05-23 18:10 ` Zack Weinberg 2025-05-24 2:24 ` Rich Felker 2025-05-24 19:25 ` Florian Weimer 2025-05-16 12:41 ` close(2) with EINTR has been changed by POSIX.1-2024 Mateusz Guzik 2025-05-16 12:41 ` Theodore Ts'o 2025-05-19 23:19 ` Steffen Nurpmeso 2025-05-20 13:37 ` Theodore Ts'o 2025-05-20 23:16 ` Steffen Nurpmeso 2025-05-16 19:13 ` Al Viro 2025-05-19 9:48 ` Christian Brauner
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).