UNIX Socket FAQ

A forum for questions and answers about network programming on Linux and all other Unix-like systems

You are not logged in.

  • Index
  • » General
  • » plink strange output buffer behavior

#1 2011-10-11 01:26 PM

xinglp
Member
Registered: 2008-04-13
Posts: 35

plink strange output buffer behavior

This is my example code, to print a line per second. With any parameters, it will print to stderr, otherwise to stdout.

#include <unistd.h>
#include <stdio.h>

int main(int argc,char* argv[])
{
	int      i;
	FILE*  f;

	f=argc>1?stderr:stdout;

	for(i=0;i<5;++i)
	{
		fprintf(f,"line %d\n",i);
		sleep(1);
	}
	return 0;
}

When I use " plink.exe user@host ./a.out " to execute it, it did not "print a line per second", but print all of the 5 lines after 5 seconds at once.
When use " plink.exe user@host ./a.out tostderr " to make it to print to stderr.  It works normal.

So I use  " plink.exe user@host strace ./a.out " to find out what happend.

rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0xbfeb37f4)           = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0xbfeb37f4)           = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0xbfeb37f4)           = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0xbfeb37f4)           = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL, [], 0}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({1, 0}, 0xbfeb37f4)           = 0
write(1, "line 0\nline 1\nline 2\nline 3\nline"..., 35) = 35
line 0
line 1
line 2
line 3
line 4
exit_group(0)                           = ?

There is only one "write(1, "line 0\nline 1\nline 2\nline 3\nline"..., 35) = 35" at last.

Then where am I wrong?

Thanks in advance

Offline

#2 2011-10-11 07:34 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: plink strange output buffer behavior

I had to lookup "plink.exe" to figure out WTF that was...  I was about to complain about you wanting us to debug some Windoze app for you...  But, it sounds like it's just PuTTY's ssh client?

Then where am I wrong?

You're not "wrong", really; you're just apparently unaware of how stdio buffering works...  stdout is always buffered by default, while stderr is never buffered by default...  If stdout is attached to a tty, then typically it should be line-buffered, in which case each newline-terminated line you output would get written out anyway, so you'd see no effective difference between stdout and stderr...  However, I'm guessing "plink" is behaving similarly to standard "ssh", and not allocating a pseudo tty when running a remote command (unless you specifically ask for one with "-t")...  So, your remote program has no tty underneath, and hence stdout gets block buffering instead of line buffering...  Ie: the same as files would get...  Ie: stdio buffers up <X> bytes of output and only writes out when it has a full buffer (or you explicitly fflush() or close the file)...

Offline

#3 2011-10-11 07:46 PM

xinglp
Member
Registered: 2008-04-13
Posts: 35

Re: plink strange output buffer behavior

RobSeace wrote:

I had to lookup "plink.exe" to figure out WTF that was...  I was about to complain about you wanting us to debug some Windoze app for you...  But, it sounds like it's just PuTTY's ssh client?

Then where am I wrong?

You're not "wrong", really; you're just apparently unaware of how stdio buffering works...  stdout is always buffered by default, while stderr is never buffered by default...  If stdout is attached to a tty, then typically it should be line-buffered, in which case each newline-terminated line you output would get written out anyway, so you'd see no effective difference between stdout and stderr...  However, I'm guessing "plink" is behaving similarly to standard "ssh", and not allocating a pseudo tty when running a remote command (unless you specifically ask for one with "-t")...  So, your remote program has no tty underneath, and hence stdout gets block buffering instead of line buffering...  Ie: the same as files would get...  Ie: stdio buffers up <X> bytes of output and only writes out when it has a full buffer (or you explicitly fflush() or close the file)...

Thanks a lot.  Plink has a "-t/-T" option too.

It's clear.

ssh -t 127.0.0.1 ls /proc/self/fd/ -ln
total 0
lrwx------ 1 1000 1000 64 Oct 12 02:42 0 -> /dev/pts/2
lrwx------ 1 1000 1000 64 Oct 12 02:42 1 -> /dev/pts/2
lrwx------ 1 1000 1000 64 Oct 12 02:42 2 -> /dev/pts/2
lr-x------ 1 1000 1000 64 Oct 12 02:42 3 -> /proc/630/fd

ssh 127.0.0.1 ls /proc/self/fd/ -ln
total 0
lr-x------ 1 1000 1000 64 Oct 12 02:44 0 -> pipe:[764]
l-wx------ 1 1000 1000 64 Oct 12 02:44 1 -> pipe:[765]
l-wx------ 1 1000 1000 64 Oct 12 02:44 2 -> pipe:[766]
lr-x------ 1 1000 1000 64 Oct 12 02:44 3 -> /proc/637/fd

plink xxx@192.168.x.x ls /proc/self/fd -ln
total 0
lr-x------ 1 1000 1000 64 Oct 12 02:45 0 -> pipe:[797]
l-wx------ 1 1000 1000 64 Oct 12 02:45 1 -> pipe:[798]
l-wx------ 1 1000 1000 64 Oct 12 02:45 2 -> pipe:[799]
lr-x------ 1 1000 1000 64 Oct 12 02:45 3 -> /proc/661/fd

plink -t xxx@192.168.x.x ls /proc/self/fd -ln
total 0
lrwx------ 1 1000 1000 64 Oct 12 02:49 0 -> /dev/pts/2
lrwx------ 1 1000 1000 64 Oct 12 02:49 1 -> /dev/pts/2
lrwx------ 1 1000 1000 64 Oct 12 02:49 2 -> /dev/pts/2
lr-x------ 1 1000 1000 64 Oct 12 02:49 3 -> /proc/667/fd

Last edited by xinglp (2011-10-11 07:50 PM)

Offline

#4 2011-10-11 07:53 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: plink strange output buffer behavior

Thanks a lot.  Plink has a "-t/-T" option too.

Oh, and if you want to make your code so that it'll work as expected even without a tty underneath, you can either add an explicit fflush() after every line or call setvbuf() on stdout to always force it line-buffered (or unbuffered, like stderr)...

Offline

#5 2011-10-11 08:51 PM

xinglp
Member
Registered: 2008-04-13
Posts: 35

Re: plink strange output buffer behavior

RobSeace wrote:

Thanks a lot.  Plink has a "-t/-T" option too.

Oh, and if you want to make your code so that it'll work as expected even without a tty underneath, you can either add an explicit fflush() after every line or call setvbuf() on stdout to always force it line-buffered (or unbuffered, like stderr)...

I just give the code for example, I'm using plink to run others, such as "gcc", "make".   
Can I do the setvbuf() work by somethings like "plink xxx@xxxx <setvbuf>; <somethings else to run>".

Last edited by xinglp (2011-10-11 09:48 PM)

Offline

#6 2011-10-12 01:20 PM

RobSeace
Administrator
From: Boston, MA
Registered: 2002-06-12
Posts: 3,826
Website

Re: plink strange output buffer behavior

Can I do the setvbuf() work by somethings like "plink xxx@xxxx <setvbuf>; <somethings else to run>".

No...  I thought it was all your own code you were running...  If dealing with others' code, you're pretty much stuck with however they wrote it (unless you want to go hacking their code and maintaining your own forked versions)...  I suppose you could do some trickery via an LD_PRELOAD library or something, but that's an ugly kluge...  Probably best to just use "-t" to get a real tty if you need one, then...

Offline

#7 2011-10-12 01:33 PM

xinglp
Member
Registered: 2008-04-13
Posts: 35

Re: plink strange output buffer behavior

Thanks, using "-t" to get a real tty is the best choice for me.

Offline

  • Index
  • » General
  • » plink strange output buffer behavior

Board footer

Powered by FluxBB