Re: GIOChannel & Intercepting stdout



On 08/25/2010 08:26 PM, Chris Vine wrote:
This won't work.  file descriptor number 1 (stdout) is a file descriptor
you write to, not read from.

If you connect stdout to the write file descriptor of a pipe with
dup2(), and then connect your GIOChannel object to the read file
descriptor of the pipe, it should work.  Whether it does or not will
depend on the libraries which you say are writing to stdout.  If they
expect a terminal on stdout you may need to resort to pseudo-ttys.

The good news is that libraries shouldn't require a terminal for stdout because then they wouldn't work with stdout being redirected to a file (highly unlikely).

The bad news is that this is harder to do correctly than it sounds. If you connect stdout to a pipe, then a thread (or a subprocess) should exist to collect output from the pipe, or the program deadlocks whenever a library prints a chunk of output larger than the pipe buffer.

The other bad news is that the dup2/pipe solution is very Unix-specific. It is not clear if this is a problem to Richard.

Here is an example code that creates a simple pipe. Hooking the read end of the pipe to GIO, and reading it in a separate thread is left as an excercise to the reader.

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

static void
printout(void)
{
  printf("foo\n");
  printf("bar\n");
  fflush(stdout);
}

static char *
collect(int fd)
{
  static char buf[512];
  int size = read(fd, buf, sizeof(buf) - 1);
  if (size < 0)
    exit(1);
  buf[size] = '\0';
  return buf;
}

int main()
{
  // create a pipe
  int pipefd[2];
  if (pipe(pipefd) < 0)
    exit(1);
  // make fd 1 alias for the write end of the pipe
  if (dup2(pipefd[1], 1) < 0)
    exit(1);
  close(pipefd[1]);
  printout();
  fprintf(stderr, "recevied: %s", collect(pipefd[0]));
  return 0;
}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]