Thread: Capturing stderr from an execv()ed process

  1. #1
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115

    Capturing stderr from an execv()ed process

    I'm trying to capture the stderr from a process which is being called by execv(). Instead, however, it seems to be writing to a descriptor that isn't even opened in this process. The short description of what I'm trying to do is I'm first creating a pipe. Then through clever use of close() and dup() I'm making the write end of the pipe STDERR_FILENO (which is 2, I believe). Then I'm calling fork() and in the child I'm calling execv(). However, the output from this process is going to the original STDERR_FILENO, not the pipe!
    A longer explanation follows:
    First, in my process I'm changing the stderr descriptor to a file
    Code:
    close(STDERR_FILENO);
    int des = open("stderr.txt", "wt");
    assert(des == STDERR_FILENO);//trust me, it works
    Then later in my program:
    Code:
    int fds[2];
    pipe(fds);
    int desBackupStderr = dup(STDERR_FILENO);//this is now a stderr
    close(STDERR_FILENO);
    int desPipeWrite = dup(fds[1]);
    assert(desPipeWrite == STDERR_FILENO);//trust me
    switch(fork()) {
        case 0://child
            close(desBackupStderr);//this process no longer has ANY descriptor open to the file stderr.txt
            CaptureLSOF();//this captures lsof -p getpid() to a file, which proves the above axiom
            const char *p = "this should make it to the read-end of the pipe";
            write(STDERR_FILENO, p, strlen(p));//this did make it into the pipe!
            execv(blah, bLah);
            assert(false);//never happens
        default://parent
             close(STDERR_FILENO);//closing write end of the pipe in the parent
             int des = dup(desBackupStderr);
             assert(des == STDERR_FILENO);//trust me
    }
    Of course, I also close unnecessary duplicate descriptors for tidiness, but I left that out of here for simplicity. What I find hard to understand is that the call to execv() has writes to the stderr going to the file stderr.txt, even though the file written by CaptureLSOF() proves that that process does not have anything open to that file. The code also proves that writes to STDERR_FILENO do make it into the pipe. It's as if the program called by execv() gets a hold the descriptor to stderr.txt through the group process id, or the parent process id? I dunno, I'm grasping at straws.
    FWIW, the program execv() is calling is sendmail (a la Postfix). I don't know what difference that could make.

    Edit - It is also worth pointing out that I have another pipe opened, whose read end is connected to the stdin of the child process. Everything I write to the pipe from the parent does make it to the stdin of the child process.
    Last edited by Angus; 11-10-2009 at 08:52 AM.

  2. #2
    Kung Fu Kitty Angus's Avatar
    Join Date
    Oct 2008
    Location
    Montreal, Canada
    Posts
    115
    N/m. It seems that when I migrated from popen() to pipe()/fork()/execv() I neglected to comment out the original popen(). I had to have an epiphany that these problems might be caused by the shell program being called twice, before I'd realize this.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Why isn't the execlp() function doing anything?
    By jsrig88 in forum C Programming
    Replies: 5
    Last Post: 10-12-2009, 10:09 AM
  2. sequenceing or queueing multiple process
    By sv_joshi_pune in forum Windows Programming
    Replies: 1
    Last Post: 08-14-2009, 09:43 AM
  3. Replies: 3
    Last Post: 10-15-2008, 09:24 AM
  4. Problem with forking a process
    By Unitedroad in forum C Programming
    Replies: 10
    Last Post: 10-04-2007, 01:43 AM
  5. process programming
    By St0rM-MaN in forum Linux Programming
    Replies: 2
    Last Post: 09-15-2007, 07:53 AM