Subject: bug#8961: stdbuf has no effect on some programs

From: Pádraig Brady <[email-masked]>
Date: Thu, 30 Jun 2011 23:54:10 +0100

On 30/06/11 20:27, Bruno Haible wrote:
> Hi Pádraig,
> 
>>> $ (echo Hello; sleep 3; echo World) | stdbuf iconv -f ASCII
>>> Hello
>>> World
>>
>> From stdbuf.c /* FIXME: Should we mandate at least one option?  */
> 
> Oops, I meant this:
> 
> $ (echo Hello; sleep 3; echo World) | stdbuf -i 0 iconv -f ASCII
> Hello
> World
> 
> Here too, the output comes only at the end, all at once.
> 
>> Anway I don't think that this works even if you specify -i0
>> because fread() only seems to return after feof() or ferror()
> 
> Exactly. So, on which kinds of programs can -i0 work?
>   - Not in programs that use read(0,...) because they are not affected
>     by LD_PRELOADs.
>   - Not in programs that use fread().
>   - Not in programs that use getc() repeatedly - because the buffering
>     behaviour of stdio is independent of whether you use fread() or [f]getc().
> Can you name a single program on which -i0 works?

Programs that use getline() for example (like sed).
They will change to reading 1 char at a time,
as will programs that use [f]getc().
I'll update the docs with details.

> 
>> int main(void)
>> {
>>     setvbuf (stdin, NULL, _IONBF, 0);
>>     setvbuf (stdout, NULL, _IONBF, 0);
> 
> But program's _don't_ call setvbuf. If a program, like 'grep', has
> an option like --line-buffered, then I don't need setvbuf.

Right, that was just a test program to simulate what `stdbuf fread_prog` does.
The raison d'être of stdbuf is to not add --line-buffered etc. to all progs
that might need it.

> 
>> I'll might add a note about fread() blocking (which POSIX requires)
>> and that setting no _buffering_ doesn't impact that.
> 
> Yes, that seems to be the point. "no buffering" != "non-blocking> Could 'stdbuf -i0' be changed to put file descriptor 0 into non-blocking state
> before invoking the child process? Is that the solution?

Well apps would need to handle EAGAIN sensibly,
and most probably don't do that.

Essentially, setting non buffered input is to limit what
the app reads (so that a subsequent app may further process stdin),
rather than changing the responsiveness to input.

cheers,
Pádraig.