This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [RFC][PATCH] Add envvar IO_BUFMODE to forcibly set buffering mode
- From: Chris Metcalf <cmetcalf at mellanox dot com>
- To: Sunyeop Lee <sunyeop97 at gmail dot com>, <libc-alpha at sourceware dot org>
- Date: Wed, 22 Mar 2017 14:36:36 -0400
- Subject: Re: [RFC][PATCH] Add envvar IO_BUFMODE to forcibly set buffering mode
- Authentication-results: sourceware.org; auth=none
- Authentication-results: sourceware.org; dkim=none (message not signed) header.d=none;sourceware.org; dmarc=none action=none header.from=mellanox.com;
- References: <CALNQmnCoN3dBqvZGk9gQkzrmvHGB3KqpPutozjDjPG0GOxe0Gw@mail.gmail.com>
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
On 3/22/2017 1:14 PM, Sunyeop Lee wrote:
I thought it's too hard and tricky to solve this problem. Some of
the solutions are: to modify the source code, to open a pty to get the
output through it, or to use LD_PRELOAD to hook printf or some
functions.
Therefore, I propose a new environment variable IO_BUFMODE to
forcibly set the buffering mode in these cases. To force "fully
buffering mode", I can easily set IO_BUFMODE=0. To force "line
buffering mode", I set IO_BUFMODE=1. And to force "no buffered mode",
I set IO_BUFMODE=2. The constants are from _IOFBF, _IOLBF, _IONBF used
in setvbuf().
A few concerns with this: it applies the change to every opened file,
which I doubt is what you want; it will make writes to files be
line-buffered at all times, which is likely not what you want. Also,
I'm not sure calling getenv() for every file open is good for
performance. And I'm a bit dubious about your just copying in the
constants _IOFBF and friends.
Here we have a similar issue in one application and found that solving
it with LD_PRELOAD was not that onerous. We wanted to spawn
subprocesses and force console stdout to be line buffered, even if the
whole process group was having its output passed into a pipe.
Accordingly, the main process does an fstat() on stdout to get its
dev/ino information and puts that into $STDIO_LBF_DEV_INO,
then sets $LD_PRELOAD to point to a trivial program that does this:
static void __attribute((constructor)) set_linebuf(void)
{
// Get "dev" and "ino" from the environment.
unsigned long dev, ino;
const char* env = getenv("STDIO_LBF_DEV_INO");
if (env == NULL || sscanf(env, "%lu:%lu", &dev, &ino) != 2)
return;
// Set line buffering if stdout is pointing to the specified dev/ino.
struct stat s;
if (fstat(STDOUT_FILENO, &s) == 0 && s.st_ino == ino && s.st_dev == dev)
setlinebuf(stdout);
}
--
Chris Metcalf, Mellanox Technologies
http://www.mellanox.com