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