Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Thu, 11 Dec 2014 18:35:32 -0500
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: stdio [de]merits discussion [Re: possible getopt
 stderr output changes]

On Fri, Dec 12, 2014 at 12:05:28AM +0100, Laurent Bercot wrote:
> On 11/12/2014 18:51, Rich Felker wrote:
> >I like it because in all but the tiniest programs, you end up needing
> >this kind of functionality, and whenever somebody rolls their own,
> >it's inevitably 10x to 100x larger and uglier than musl's printf core.
> 
>  You haven't tried skalibs. ;)

I'm not thinking of thing I've tried using myself but rather things
I've seen in mainstream, deployed software. Hideous stuff like APR.
Let me know when you convince folks using APR, NSPR, etc. to switch to
skalibs. :-)

I suppose my use of the word "inevitably" was wrong, but I was trying
to talk about stuff I've seen happen in the wild rather than what's in
the realm of possibility.

> >This is solved by fflush before fclose.
> 
>  I'm surprised that you of all people say this. What if another thread
> writes to the FILE between the fflush and the fclose ? Granted, if the
> situation arises, it's probably a programming error, but still, since
> atomicity is a big thing for FILE, needing 2 operations instead of 1
> doesn't scream good design.

In that case you have UB, since the write from another thread could
equally happen after the fclose (it's unsynchronized) resulting in use
of an invalid FILE*. So it's not an interesting case. The point being:
you can't close a FILE without ensuring that no other threads could
still be accessing it. In practice, aside from the standard streams,
it's really unusual to have simultaneous accesses to the same stream
from multiple threads anyway.

> >GNU software (gnulib in particular) likes to ignore this problem by poking
> >at internals; we gave them an alternate solution with musl a couple
> >years back just to avoid this. :(
> 
>  Jesus. And you still argue that it's a usable interface, if people have
> to hack internal implementation details to get a simple readability
> notification working ?

No, I think this is a misuse of it for something it's not good for. I
don't advocate this kind of hackery at all. The only reason I went to
the effort to support it and negotiate a solution with the gnulib
people was that otherwise we risked them writing hacks to poke at the
internals, which are intentionally allowed to change between versions
of libc.so, thereby making binaries that crash and burn when libc.so
is upgraded. Given rate of musl adoption at the time, this would have
just made musl look bad, even if it was 100% their fault. It would
also have been a big mess for distros to fix.

> >For event-driven models, yes. For threaded models, it's quite usable
> >and IMO it simplifies code by a a larger factor than the size it adds,
> >in cases where it's sufficient.
> 
>  "If you can't write asynchronous code, use threads and write synchronous
> code." :-Þ
>  I agree that threads are a good paradigm to have, but the choice of
> which model to use should not be dictated by the indigence of available
> interfaces.

Agreed. I think stdio is a good choice for many things if you are
using threads though.

> >The big thing it provides here is a standard point of synchronization
> >for error messages in multithreaded programs. Otherwise there would be
> >no lock for different library components to agree on to prevent
> >interleaved error output.
> 
>  write() guarantees atomicity up to PIPE_BUF bytes. I have never seen
> an stderr error message that was bigger than that.

Only for pipes. Ordinary files are also required by POSIX to have
atomic write(), but Linux fails to deliver on this requirement, and
the only correct way for a kernel to deliver is by returning a short
write (which undermines the atomicity) when the full write would
sleep. Terminals have no atomicity at all.

Stdio cannot make the fd atomic, but it does make _arbitrarily large_
output atomic within a single process (i.e. assuming other processes
aren't writing to the file at the same time) simply by doing the
locking in userspace where it's not a DoS issue.

> >Yes and no. There are some things that could have been done better,
> >and some backwards-compatible additions that could be made to make it
> >a lot more useful, but I think stdio still largely succeeds in freeing
> >the programmer from having to spend lots of effort on IO code, for a
> >large class of useful programs (certainly not all, though!).
> 
>  I agree it's good enough for Hello World and applications that just
> need very basic I/O.

I think it also works fine for basically all programs that fit the
unix model of running as a "do one thing and do it well" utility that
reads input from stdin and/or one or more files and writes output to
one file (possibly stdout).

> What irks me is that stdio sets a potential barrier
> to designing better I/O interfaces, and people who need reliable I/O
> management often still contort themselves to use stdio, and the results
> are ugly. See the aforementioned gnulib case.

Perhaps I should look at how skalibs does it.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.