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.

#1 2008-01-25 11:16 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: fork() vs setlinebuf()

Hi all,

In my continuing quest to fork() a child process and interact with it, I've come across another small problem:  stdout buffering.  It appears that when a process starts up, the C runtime(?) detects whether the process's STDOUT_FILENO is associated with a TTY or not.  If it is, it sets stdout to line-buffering mode (via setlinebuf(stdout), or something equvalent to that), and if it's not, it sets stdout to fully buffered mode.

That's fine, except in the case where neither the parent nor child process are associated with a TTY, AND the parent process needs to respond to the child's output ASAP.  Then the fully-buffered stdout mode gets in the way; for example, if the child just prints out a single short line of text and then waits indefinitely, the parent process will never see that line of text.

What I'd like to do is force the child process to use line-buffered mode for stdout, no matter what.  That's easy enough to accomplish if I have control over the child's source code... I can just add a setlinebuf(stdout) call to the top of the child's main() and everything works.  But I'd like to also do the right thing for child processes I can't modify.  Calling setlinebuf(stdout) just before the call to exec() doesn't have an effect; presumably because the detect-TTY-and-set-buffering-mode routine is called after exec() starts.

Another method would be to use termios on the child, and that works fine, but only if the parent has a TTY associated with it.  If the parent has no TTY associated, then tcgetattr() (etc) fail and the I/O doesn't work properly.

So, does anyone know of a way to trick the child process into calling setlinebuf(stdout) on itself during startup, without modifying the child process's source code, and without requiring a TTY?

Thanks,
Jeremy

Offline

#2 2008-01-26 01:52 AM

i3839
Oddministrator
From: Amsterdam
Registered: 2003-06-07
Posts: 2,239

Re: fork() vs setlinebuf()

Doing e.g. an openpty() shouldn't be too much trouble, is it?

That means "no". ;-)

Offline

#3 2008-01-26 07:34 PM

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

Re: fork() vs setlinebuf()

Yeah, i3839 is right...  The standard option for working around this behavior is to
use a pseudo-tty, so the child thinks its stdout is really a tty...

One other ugly kluge that could be done instead on any system with shared libraries
is to create a lib that forces the line-buffering on stdout and have that LD_PRELOAD'd
into your exec*()'d app, so it executes within it...  You may not be able to get away
with a simple init/constructor function, because it'll likely be loaded before even glibc,
so before it has done the full-buffering to stdout yet...  So, you'd probably have to
simply replace some common function you know is going to be called by the app or
other libs, and do the job there, and call the real function with dlsym(RTLD_NEXT)...
Horridly ugly, but theoretically possible...

Offline

#4 2008-01-28 08:09 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: fork() vs setlinebuf()

Offline

#5 2008-01-28 08:36 PM

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

Re: fork() vs setlinebuf()

Yeah, that should work fine, I think...  As long as the child process that's using the pty
doesn't use curses or need any other fancy terminal features, anyway...

Offline

#6 2008-01-28 08:44 PM

jfriesne
Administrator
From: California
Registered: 2005-07-06
Posts: 348
Website

Re: fork() vs setlinebuf()

Offline

Board footer

Powered by FluxBB