bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: rationale for closein


From: Rich Felker
Subject: Re: rationale for closein
Date: Mon, 18 Jun 2012 20:01:54 -0400
User-agent: Mutt/1.5.21 (2010-09-15)

On Tue, Jun 19, 2012 at 01:28:24AM +0200, Bruno Haible wrote:
> Rich Felker wrote in
> <http://www.openwall.com/lists/musl/2012/06/18/8>:
> > I've already discussed on this list why using an atexit function for
> > closing stdin or stdout is the heart of the problem and the source of
> > all the complexity. If the main program just closed the stream at the
> > natural point in the normal program flow, it would be trivial to do
> > correctly and portably.
> 
> Here's how this 'closein' module came about:
> 
> Jim, maintainer of coreutils (a set of ca. 100 programs), noticed that
> the programs failed to report an error when writing to a full disk. Not only
>   $ cat file1 file2 > /full-partition/output
> but also
>   $ id -u > /full-partition/output
> or
>   $ sort --help > /full-partition/output
> 
> The problem is that not only the "normal program flow" needs to be
> considered, but all program flows from the start of main() to exit().
> He could have changed the source code of all 100 programs so that this
> bug would be fixed, but that would not give a guarantee that the bug would
> not be reintroduced as new code branches are added in existing programs,
> or as new programs are being written. So he searched for a solution that
> would prevent the bug from reappearing and also not increase the maintenance
> burden, and came up with 'closeout'.
> 
> Jim made a presentation about this:
> http://www.gnu.org/ghm/2011/paris/#sec-2-1
> http://www.irill.org/events/ghm-gnu-hackers-meeting/videos/jim-meyering-goodbye-world-the-perils-of-relying-on-output-streams-in-c

Yes, I've seen it; it was discussed on our list. I wasn't aware of the
specific historic details, but I figured this was probably the general
story for how the idea came to be.

If the "closeout" approach works best for coreutils, that's the
business of the coreutils' maintainers, not my business. However, as I
discussed on the musl list, I think it's bad design, and I would
highly recommend other projects not follow it. Conceptually, you're
turning something that's a local variable (stdout is global, but if
it's only used from one point as a generic FILE standing in for
something that would otherwise have been obtained by fopen, it's
conceptually local) into a global, and thereby losing the _local_
information of whether it was used in the first place, which has to be
recovered with the non-portable __fpending.

If on the other hand programs just handle stdout as "yet another
FILE", the same code that checks for write errors and reports failure
for explicitly-opened files would also check and report write errors
on stdout. It's not longer a special-case. And special-cases are where
errors like to hide.

> 'closein' is similar - an attempt to fix an issue that affects many programs,
> once and for all. By Eric Blake.

I think closein is just a no-op for conformant implementations. exit
implicitly closes all streams, including stdin, and per POSIX, fclose
has the following effect:

    If the file is not already at EOF, and the file is one capable of
    seeking, the file offset of the underlying open file description
    shall be adjusted so that the next operation on the open file
    description deals with the byte after the last one read from or
    written to the stream being closed.

As such, close_stdin's attempt to fix-up the file position seems to be
redundant.

Incidentally, I suspect musl is _not_ currently handling this case
correctly. Does gnulib have some tests that assert the required
behavior, which I could use to test the current behavior and any
efforts to fix it if it's wrong?

(If it is broken in musl, it's due to stdin being a special case in
musl. Alas, special cases are where errors like to hide...)

Rich



reply via email to

[Prev in Thread] Current Thread [Next in Thread]