Fog Creek Software
g
Discussion Board




Unix & c redirection question ?

Hello, please tell me why my c program for i/o redirection doesn't work, i.e. didn't see output from redirected stdout, but works for stderr :

int main(void)
{
  int logf=0;
  int errf=0;

  logf = creat("log.log",0666);
  errf = creat("err.log",0666);

  dup2(logf,1);
  dup2(errf,2);

  while(1)
  {
      puts("This is puts\n");                /* not work */
      fprintf(stdout, "This is fprintf\n");  /* not work */
      fprintf(stderr, "This is err\n");      /* works */
      sleep(30);
  }

  exit(0);
}

Li Hu
Wednesday, February 25, 2004

Maybe your dup2 for FD 1 (ie, what you're assuing is
bound to stdout) failed for some reason?

You may want to error-check those calls and see if
that's a reason.

Also, this approach makes several unportable (but
common) assumptions about the underlying
FS implementation.  Lots of FS implementations I've
seen in the embedded world don't implement the "layered"
approach that you're code relies on.  You're
assuming that the POSIX FS API (ie, dup2, creat) is
underneath and the STDIO FS API (puts, fprintf, etc) is
built on top of it.  This isn't always true.

x
Wednesday, February 25, 2004

maybe it's buffered,


Wednesday, February 25, 2004

Buffering shouldn't make any difference, because when you call exit(), it will close all open FDs which will flush them.

Katie Lucas
Wednesday, February 25, 2004

Of course, CTRL-Cing it doesn't call exit().

I'll get me coat...

Katie Lucas
Wednesday, February 25, 2004

Actually, posix I/O does no buffering - this is where one
can get into trouble with this approach.  Even if you
gracefully exit, you're subject to the order in which exit()
calls the API wrapup routines - if the POSIX API wrapup
is called before the STDIO wrapup, STDIO can't flush
its buffers - because the fd is already closed - and you'll
lose.

A better and safer scheme for logging is to write a little
API function like

void
loggit(char *logmsg)

{
    extern FILE *logfp;  /* assumed to be already open */

    fprintf(stderr, "%s\n", logmsg);
    fprintf(logfp, "%s\n", logmsg);

    fflush(stderr); /* usually not necessary, but won't hurt */   

    /* More necessary - if you crash, you'll lose the buffer
    * and the all-important log message as to what
    * was happening just before the crash!
    */

    fflush(logfp);
}

(An aside: don't use

fprintf(stderr, logmsg);

If logmsg happens to have a percent sign in it, fprintf
will expect an argument and you'll get a crash.)
   

x
Wednesday, February 25, 2004

Thank you very much indeed !

The problem is bufferring-related. Using setbuf or fflush
gets output properly.

Li Hu
Thursday, February 26, 2004

*  Recent Topics

*  Fog Creek Home