public inbox for linux-fsdevel@vger.kernel.org
 help / color / mirror / Atom feed
From: Alejandro Colomar <alx@kernel.org>
To: Rich Felker <dalias@libc.org>
Cc: Zack Weinberg <zack@owlfolio.org>,
	 Vincent Lefevre <vincent@vinc17.net>, Jan Kara <jack@suse.cz>,
	 Alexander Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>,
	 linux-fsdevel@vger.kernel.org, linux-api@vger.kernel.org,
	 GNU libc development <libc-alpha@sourceware.org>
Subject: Re: [RFC v1] man/man2/close.2: CAVEATS: Document divergence from POSIX.1-2024
Date: Tue, 20 Jan 2026 21:42:33 +0100	[thread overview]
Message-ID: <aW_olRn5s1lbbjdH@devuan> (raw)
In-Reply-To: <aW_jz7nucPBjhu0C@devuan>

[-- Attachment #1: Type: text/plain, Size: 9759 bytes --]

On Tue, Jan 20, 2026 at 09:35:43PM +0100, Alejandro Colomar wrote:
> Hi Rich, Zack,
> 
> On Tue, Jan 20, 2026 at 12:46:59PM -0500, Rich Felker wrote:
> > On Tue, Jan 20, 2026 at 12:05:52PM -0500, Zack Weinberg wrote:
> > > > On Fri, May 23, 2025 at 02:10:57PM -0400, Zack Weinberg wrote:
> 
> [...]
> 
> > > Now, the abstract correct behavior is secondary to the fact that we
> > > know there are both systems where close should not be retried after
> > > EINTR (Linux) and systems where the fd is still open after EINTR
> > > (HP-UX).  But it is my position that *portable code* should assume the
> > > Linux behavior, because that is the safest option.  If you assume the
> > > HP-UX behavior on a machine that implements the Linux behavior, you
> > > might close some unrelated file out from under yourself (probably but
> > > not necessarily a different thread).  If you assume the Linux behavior
> > > on a machine that implements the HP-UX behavior, you have leaked a
> > > file descriptor; the worst things that can do are much less severe.
> > 
> > Unfortunately, regardless of what happens, code portable to old
> > systems needs to avoid getting in the situation to begin with. By
> > either not installing interrupting signal handlers or blocking EINTR
> > around close.
> 
> [...]
> 
> > > > 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.
> > > 
> > > I could be persuaded to tone it down a little but in this case I think
> > > the man page's job *is* to tell people how to program.  We know lots of
> > > existing code has gotten the fine details of close() wrong and we are
> > > trying to document how to do it right.
> > 
> > No, the job of the man pages absolutely is not "to tell people how to
> > program". It's to document behaviors. They are not a programming
> > tutorial. They are not polemic diatribes. They are unbiased statements
> > of facts. Facts of what the standards say and what implementations do,
> > that equip programmers with the knowledge they need to make their own
> > informed decisions, rather than blindly following what someone who
> > thinks they know better told them to do.
> 
> This reminds me a little bit of the realloc(p,0) fiasco of C89 and
> glibc.
> 
> In most cases, I agree with you that manual pages are and should be
> aseptic, there are cases where I think the manual page needs to be
> tutorial.  Especially when there's such a mess, we need to both explain
> all the possible behaviors (or at least mention them to some degree).

... and guide programmers about how to best use the API.

I forgot to finish the sentence.

> 
> But for example, there's the case of realloc(p,0), where we have
> a fiasco that was pushed by a compoundment of wrong decisions by the
> C Committee, and prior to that from System V.  We're a bit lucky that
> C17 accidentally broke it so badly that we now have it as UB, and that
> gives us the opportunity to fix it now (which BTW might also be the case
> for close(2)).
> 
> In the case of realloc(3), I went and documented in the manual page that
> glibc is broken, and that ISO C is also broken.
> 
> 	STANDARDS
> 	     malloc()
> 	     free()
> 	     calloc()
> 	     realloc()
> 		    C23, POSIX.1‐2024.
> 
> 	     reallocarray()
> 		    POSIX.1‐2024.
> 
> 	   realloc(p, 0)
> 	     The  behavior of realloc(p, 0) in glibc doesn’t conform to
> 	     any of C99, C11, POSIX.1‐2001, POSIX.1‐2004, POSIX.1‐2008,
> 	     POSIX.1‐2013,  POSIX.1‐2017,  or  POSIX.1‐2024.   The  C17
> 	     specification  was changed to make it conforming, but that
> 	     specification made it impossible to write code that  reli‐
> 	     ably  determines if the input pointer is freed after real‐
> 	     loc(p, 0), and C23 changed it again to make this undefined
> 	     behavior, acknowledging that  the  C17  specification  was
> 	     broad enough, so that undefined behavior wasn’t worse than
> 	     that.
> 
> 	     reallocarray() suffers the same issues in glibc.
> 
> 	     musl  libc  and  the BSDs conform to all versions of ISO C
> 	     and POSIX.1.
> 
> 	     gnulib provides the realloc‐posix module,  which  provides
> 	     wrappers  realloc() and reallocarray() that conform to all
> 	     versions of ISO C and POSIX.1.
> 
> 	     There’s a proposal to standardize the BSD behavior: https:
> 	     //www.open-std.org/jtc1/sc22/wg14/www/docs/n3621.txt.
> 
> 	HISTORY
> 	     malloc()
> 	     free()
> 	     calloc()
> 	     realloc()
> 		    POSIX.1‐2001, C89.
> 
> 	     reallocarray()
> 		    glibc 2.26.  OpenBSD 5.6, FreeBSD 11.0.
> 
> 	     malloc() and related functions rejected sizes greater than
> 	     PTRDIFF_MAX starting in glibc 2.30.
> 
> 	     free() preserved errno starting in glibc 2.33.
> 
> 	   realloc(p, 0)
> 	     C89 was ambiguous in its specification of  realloc(p,  0).
> 	     C99 partially fixed this.
> 
> 	     The  original implementation in glibc would have been con‐
> 	     forming to C99.  However, and ironically, trying to comply
> 	     with C99 before the standard was released,  glibc  changed
> 	     its  behavior  in glibc 2.1.1 into something that ended up
> 	     not conforming to the final C99 specification (but this is
> 	     debated, as the wording of the standard seems self‐contra‐
> 	     dicting).
> 
> 	...
> 
> 	BUGS
> 	     Programmers  would  naturally  expect  by  induction  that
> 	     realloc(p, size)  is  consistent  with  free(p)  and  mal‐
> 	     loc(size),  as  that  is the behavior in the general case.
> 	     This is not explicitly required by  POSIX.1‐2024  or  C11,
> 	     but  all  conforming  implementations  are consistent with
> 	     that.
> 
> 	     The glibc implementation of realloc()  is  not  consistent
> 	     with  that,  and as a consequence, it is dangerous to call
> 	     realloc(p, 0) in glibc.
> 
> 	     A  trivial  workaround  for  glibc  is   calling   it   as
> 	     realloc(p, size?size:1).
> 
> 	     The  workaround for reallocarray() in glibc ——which shares
> 	     the         same          bug——          would          be
> 	     reallocarray(p, n?n:1, size?size:1).
> 
> 
> Apart from documenting that glibc and ISO C are broken, we document how
> to best deal with it (see the last paragraph in BUGS).  This is
> necessary because I fear that just by documenting the different
> behaviors, programmers would still not know what to do with that.
> Just take into account that even several members of the committee don't
> know how to deal with it.
> 
> I'd be willing to have something similar for close(2).
> 
> 
> Have a lovely night!
> Alex
> 
> P.S.:  I have great news about realloc(p,0)!  Microsoft is on-board with
> the change.  They told me they like the proposal, and are willing to
> fix their realloc(3) implementation.  They'll now conduct tests to make
> sure it doesn't break anything too badly, and will come back to me with
> any feedback they have from those tests.
> 
> I'll put the standards proposal for realloc(3) on hold, waiting for
> Microsoft's feedback.
> 
> > > > 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.
> > > 
> > > The correct way to address this would be to make close() not be a
> > > cancellation point.
> > 
> > This would also be a desirable change, one I would support if other
> > implementors are on-board with pushing for it.
> > 
> > > > 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).
> > > 
> > > This outline seems more or less reasonable to me but, if it's me
> > > writing the text, I _will_ characterize what POSIX currently says
> > > about EINTR returns from close() as a bug in POSIX.  As far as I'm
> > > concerned, that is a fact, not polemic.
> > > 
> > > I have found that arguing with you in particular, Rich, is generally
> > > not worth the effort.  Therefore, unless you reply and _accept_ that
> > > the final version of the close manpage will say that POSIX is buggy,
> > > I am not going to write another version of this text, nor will I be
> > > drawn into further debate.
> > 
> > I will not accept that because it's a gross violation of the
> > responsibility of document writing.
> > 
> > Rich
> 
> -- 
> <https://www.alejandro-colomar.es>



-- 
<https://www.alejandro-colomar.es>

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

  reply	other threads:[~2026-01-20 20:42 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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
2026-01-20 17:05                   ` Zack Weinberg
2026-01-20 17:46                     ` Rich Felker
2026-01-20 18:39                       ` Florian Weimer
2026-01-20 19:00                         ` Rich Felker
2026-01-20 20:05                           ` Florian Weimer
2026-01-20 20:11                       ` Paul Eggert
2026-01-20 20:35                       ` Alejandro Colomar
2026-01-20 20:42                         ` Alejandro Colomar [this message]
2026-01-23  0:33                           ` Zack Weinberg
2026-01-23  1:02                             ` Alejandro Colomar
2026-01-23  1:38                               ` Al Viro
2026-01-23 14:44                                 ` Alejandro Colomar
2026-01-23 14:05                               ` Zack Weinberg
2026-01-24 19:34                             ` The 8472
2026-01-24 21:39                               ` Rich Felker
2026-01-24 21:57                                 ` The 8472
2026-01-25 15:37                                   ` Zack Weinberg
2026-01-26  8:51                                     ` Florian Weimer
2026-01-26 12:15                                     ` Jan Kara
2026-01-26 13:53                                       ` The 8472
2026-01-26 15:56                                         ` Jan Kara
2026-01-26 16:43                                           ` Jeff Layton
2026-01-26 23:01                                             ` Trevor Gross
2026-01-27  0:49                                               ` Jeff Layton
2026-01-28 16:58                                                 ` Zack Weinberg
2026-02-05  9:34                                                   ` Jan Kara
2025-05-24 19:25                 ` Florian Weimer
2026-01-18 22:23                 ` Alejandro Colomar
2026-01-20 16:15                   ` Zack Weinberg
2026-01-20 16:36                     ` Rich Felker
2026-01-20 19:17                       ` Al Viro
2026-02-06 15:13             ` Vincent Lefevre
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

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=aW_olRn5s1lbbjdH@devuan \
    --to=alx@kernel.org \
    --cc=brauner@kernel.org \
    --cc=dalias@libc.org \
    --cc=jack@suse.cz \
    --cc=libc-alpha@sourceware.org \
    --cc=linux-api@vger.kernel.org \
    --cc=linux-fsdevel@vger.kernel.org \
    --cc=vincent@vinc17.net \
    --cc=viro@zeniv.linux.org.uk \
    --cc=zack@owlfolio.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox