ordering of printed lines changes when redirecting

2016-07-18 Thread walter harms

Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: linux-gnu
Compiler: gcc -I/home/abuild/rpmbuild/BUILD/bash-4.2 
-L/home/abuild/rpmbuild/BUILD/bash-4.2/../readline-6.2
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu'
-DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash' -DSHELL 
-DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib
-fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2 
-fstack-protector -funwind-tables -fasynchronous-unwind-tables -g
-D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g -Wuninitialized -Wextra 
-Wno-unprototyped-calls -Wno-switch-enum -Wno-unused-variable
-Wno-unused-parameter -ftree-loop-linear -pipe -DBNC382214=0 -fprofile-use
uname output: Linux omnfr121 4.5.0-4.g3d86af7-default #1 SMP PREEMPT Fri Mar 18 
13:03:45 UTC 2016 (3d86af7) x86_64 x86_64 x86_64 GNU/Linux
Machine Type: x86_64-suse-linux-gnu

Bash Version: 4.2
Patch Level: 47
Release Status: release

Description:   ordering of printed lines changes when merging stdin/stdout and 
redirecting


Repeat-By:

#include 

int main()
{
printf("hallo %d\n",__LINE__);
fprintf(stderr,"hallo %d\n",__LINE__);
printf("hallo %d\n",__LINE__);
fprintf(stderr,"hallo %d\n",__LINE__);
printf("hallo %d\n",__LINE__);

return 0;
}

compile: gcc prg.c

then:
 ( ./a.out 2>&1 )
hallo 5
hallo 6
hallo 7
hallo 8
hallo 9

( ./a.out 2>&1 ) >xx
cat xx
hallo 6
hallo 8
hallo 5
hallo 7
hallo 9

note: the same happens with
./a.out  >xx 2>&1
 cat xx
hallo 6
hallo 8
hallo 5
hallo 7
hallo 9

I am not sure if that is an intended behavior. at least it is annoying
when trying to analyze bugs.
If this is intended behavior it would be nice if that would be included
into the manual (i have found no hint, maybe wrong keyword ?) and a way
to fix that.

re,
 wh



Re: ordering of printed lines changes when redirecting

2016-07-18 Thread Pierre Gaston
On Mon, Jul 18, 2016 at 11:22 AM, walter harms  wrote:

>
> Configuration Information [Automatically generated, do not change]:
> Machine: x86_64
> OS: linux-gnu
> Compiler: gcc -I/home/abuild/rpmbuild/BUILD/bash-4.2
> -L/home/abuild/rpmbuild/BUILD/bash-4.2/../readline-6.2
> Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
> -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-suse-linux-gnu'
> -DCONF_VENDOR='suse' -DLOCALEDIR='/usr/share/locale' -DPACKAGE='bash'
> -DSHELL -DHAVE_CONFIG_H   -I.  -I. -I./include -I./lib
> -fmessage-length=0 -grecord-gcc-switches -O2 -Wall -D_FORTIFY_SOURCE=2
> -fstack-protector -funwind-tables -fasynchronous-unwind-tables -g
> -D_GNU_SOURCE -DRECYCLES_PIDS -Wall -g -Wuninitialized -Wextra
> -Wno-unprototyped-calls -Wno-switch-enum -Wno-unused-variable
> -Wno-unused-parameter -ftree-loop-linear -pipe -DBNC382214=0 -fprofile-use
> uname output: Linux omnfr121 4.5.0-4.g3d86af7-default #1 SMP PREEMPT Fri
> Mar 18 13:03:45 UTC 2016 (3d86af7) x86_64 x86_64 x86_64 GNU/Linux
> Machine Type: x86_64-suse-linux-gnu
>
> Bash Version: 4.2
> Patch Level: 47
> Release Status: release
>
> Description:   ordering of printed lines changes when merging stdin/stdout
> and redirecting
>
>
The problem is that buffering of stdout changes depending on where it goes
(line buffered in a terminal, fully buffered in a file), see for instance:

http://www.pixelbeat.org/programming/stdio_buffering/

This should be documented in your libc library.

You could flush stdout in your program, for other workarounds see
http://mywiki.wooledge.org/BashFAQ/009


Re: ordering of printed lines changes when redirecting

2016-07-18 Thread Greg Wooledge
On Mon, Jul 18, 2016 at 10:22:46AM +0200, walter harms wrote:
>  ( ./a.out 2>&1 )
> hallo 5
> hallo 6
> hallo 7
> hallo 8
> hallo 9

(snip)

> ./a.out  >xx 2>&1
>  cat xx
> hallo 6
> hallo 8
> hallo 5
> hallo 7
> hallo 9

Looks like an artifact of stdio (libc) buffering.  When stdout and
stderr are going to a terminal (first example), you get line buffering
(flushed after each newline), and thus the order you expect.  When stdout
and stderr are going to a file, you get much larger buffers.  Looks like
the flush happens implicitly when the program exits.  In your second
example here, you happen to get all of the stderr lines first, followed
by all of the stdout lines.

See if the behavior changes when you add these lines to the start of
the C program:

setvbuf(stdout, NULL, _IOLBF, 0);
setvbuf(stderr, NULL, _IOLBF, 0);



Re: ordering of printed lines changes when redirecting

2016-07-18 Thread walter harms


Am 18.07.2016 15:59, schrieb Greg Wooledge:
> On Mon, Jul 18, 2016 at 10:22:46AM +0200, walter harms wrote:
>>  ( ./a.out 2>&1 )
>> hallo 5
>> hallo 6
>> hallo 7
>> hallo 8
>> hallo 9
> 
> (snip)
> 
>> ./a.out  >xx 2>&1
>>  cat xx
>> hallo 6
>> hallo 8
>> hallo 5
>> hallo 7
>> hallo 9
> 
> Looks like an artifact of stdio (libc) buffering.  When stdout and
> stderr are going to a terminal (first example), you get line buffering
> (flushed after each newline), and thus the order you expect.  When stdout
> and stderr are going to a file, you get much larger buffers.  Looks like
> the flush happens implicitly when the program exits.  In your second
> example here, you happen to get all of the stderr lines first, followed
> by all of the stdout lines.
> 
> See if the behavior changes when you add these lines to the start of
> the C program:
> 
> setvbuf(stdout, NULL, _IOLBF, 0);
> setvbuf(stderr, NULL, _IOLBF, 0);

thx for the fast reply, my testprogramm works as expected after the changes.

My basic mistake was that my understand was that \n should flush the buffer,
that was obviously wrong.

NTL i would recommend to add one or two line about buffering into
the ducomentation :)

thx for help,

re,
 wh






Re: ordering of printed lines changes when redirecting

2016-07-18 Thread Chet Ramey
On 7/18/16 10:11 AM, walter harms wrote:

> NTL i would recommend to add one or two line about buffering into
> the ducomentation :)

It's already documented in the right place:

https://www.gnu.org/software/libc/manual/html_node/Stream-Buffering.html#Stream-Buffering


-- 
``The lyf so short, the craft so long to lerne.'' - Chaucer
 ``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, UTech, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/



Re: ordering of printed lines changes when redirecting

2016-07-18 Thread walter harms


Am 18.07.2016 16:36, schrieb Chet Ramey:
> On 7/18/16 10:11 AM, walter harms wrote:
> 
>> NTL i would recommend to add one or two line about buffering into
>> the ducomentation :)
> 
> It's already documented in the right place:
> 
> https://www.gnu.org/software/libc/manual/html_node/Stream-Buffering.html#Stream-Buffering
> 
> 

to be serious, who will look into libc documentation when
./a.out >xx 2>&1   and  ./a.out 2>&1   behave differently ?

They will, as i did, check if there is something special with redirections.

what about:

Note:
be aware that when merging output (e.g. 2&>1) the sequence can differ depending
on the buffering used by your programm. use setvbuf() to control buffering.
see also: 
https://www.gnu.org/software/libc/manual/html_node/Stream-Buffering.html#Stream-Buffering
or see man setvbuf

adjust as you like

re,
 wh




Re: ordering of printed lines changes when redirecting

2016-07-18 Thread Pádraig Brady
On 18/07/16 14:59, Greg Wooledge wrote:
> On Mon, Jul 18, 2016 at 10:22:46AM +0200, walter harms wrote:
>>  ( ./a.out 2>&1 )
>> hallo 5
>> hallo 6
>> hallo 7
>> hallo 8
>> hallo 9
> 
> (snip)
> 
>> ./a.out  >xx 2>&1
>>  cat xx
>> hallo 6
>> hallo 8
>> hallo 5
>> hallo 7
>> hallo 9
> 
> Looks like an artifact of stdio (libc) buffering.  When stdout and
> stderr are going to a terminal (first example), you get line buffering
> (flushed after each newline), and thus the order you expect.  When stdout
> and stderr are going to a file, you get much larger buffers.  Looks like
> the flush happens implicitly when the program exits.  In your second
> example here, you happen to get all of the stderr lines first, followed
> by all of the stdout lines.
> 
> See if the behavior changes when you add these lines to the start of
> the C program:
> 
> setvbuf(stdout, NULL, _IOLBF, 0);
> setvbuf(stderr, NULL, _IOLBF, 0);

One might be able to control from outside the program as well like:

stdbuf -oL your_prog