1

I want to analyse the output of strace in my C++ program. While launching /bin/strace ps from my app I get an output from ps, but not from strace and strace output is printed to stdout (my terminal). I use standard technique of using pipes and redirecting streams.

Here is my source:

#include <stdlib.h> 
#include <iostream> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <fcntl.h>
int main(){
    char *const parmList[] = {"/bin/strace", "ps", NULL};
    int pipes[2];
    pipe(pipes);
    pid_t child = fork();
    if(child == 0){
        close(pipes[0]);
        dup2(pipes[1],1);
        execv(parmList[0], parmList);
    }
    else{
        int status;
        wait(&status);

        fcntl(pipes[0], F_SETFL, O_NONBLOCK | O_ASYNC); 
        char buf[128] = {0}; 
        ssize_t bytesRead; 
        std::string stdOutBuf; 
        while(1) {
            bytesRead = read(pipes[0], buf, sizeof(buf)-1);
            if (bytesRead <= 0)
                break;
            buf[bytesRead] = 0;
            stdOutBuf += buf;
        } 
        std::cout << "<stdout>\n" << stdOutBuf << "\n</stdout>" << std::endl; 
    }

    close(pipes[0]);
    close(pipes[1]);

    return 0;
 }

How can I get an output of strace in my program?

n-canter
  • 268
  • 1
  • 11

1 Answers1

1

strace writes to stderr not to stdout, if you only want to capture the strace output just use stderr instead of stdout

change the dup2 line like this

     dup2(pipes[1],2);

If you want combined strace and ps output do this:

    dup2(pipes[1],1);
    dup2(pipes[1],2);

if you want separated output you'll probably need to use non-blocking reads and select() or poll()

Also: after calling exec you should print an error message, if everything works exec won't return, but if something goes wrong with the exec, it's good to know.

std::cerr << "exec failed!";

I used this code and had success:

#include <stdlib.h> 
#include <iostream> 
#include <sys/types.h> 
#include <sys/wait.h> 
#include <unistd.h> 
#include <fcntl.h>
int main(){
    char *const parmList[] = {"/usr/bin/strace", "ps", NULL};
    int pipes[2];
    pipe(pipes);
    pid_t child = fork();
    if(child == 0){
        close(pipes[0]);
        dup2(pipes[1],2);
        execv(parmList[0], parmList);
          std::cerr << "exec fail\n" ;
    }
    else{               
        int status;
        wait(&status);

        fcntl(pipes[0], F_SETFL, O_NONBLOCK | O_ASYNC); 
        char buf[128] = {0}; 
        ssize_t bytesRead; 
        std::string stdOutBuf; 
        while(1) {
            bytesRead = read(pipes[0], buf, sizeof(buf)-1);
            if (bytesRead <= 0)
                break;
            buf[bytesRead] = 0;
            stdOutBuf += buf;
        } 
        std::cout << "<stdout>\n" << stdOutBuf << "\n</stdout>" << std::endl; 
    }
    close(pipes[0]);
    close(pipes[1]);

    return 0;
}

HTH

Jasen
  • 11,837
  • 2
  • 30
  • 48
  • Thank you for your reply, but if I redirect stderr then it hangs completely, even in case when all the parent is doing is wait(&status) – n-canter Dec 23 '14 at 07:36
  • hmm, it should work. I can't get your source to compile. – Jasen Dec 23 '14 at 07:54
  • strange, I compile it with g++ 4.9.1, it gives some warnings because of deprecated conversion, but it compiles – n-canter Dec 23 '14 at 08:07
  • thanks, for some reason I was trying to use gcc :(. when it compiled I dicovered I also had to change the path on strace to `"/usr/bin/strace"` and then it worked as I expected. – Jasen Dec 23 '14 at 08:30
  • Thanks for your help, it turned out that it hangs only while using ps... It's very strange, may be smth specific with my archlinux – n-canter Dec 23 '14 at 16:04
  • smth weird is going on, your code hangs on my system, I'll try to investigate it, and will let you know if I find out smth interesting. – n-canter Dec 24 '14 at 11:07