In multi thread application how can I redirect std

2020-02-09 19:19发布

I have multi thread application in which I'm creating a thread like this:

int main(int argc,char *argv[])
{
    pthread_t thread_id[argc-1];
    int i;
    struct parameter thread_data[argc-1];
    int status;
    for(i=0;i<argc-1;i++)
    {
      thread_data[i].ip_filename = argv[i+1];
      strcpy (thread_data[i].op_filename,argv[i+1]);
      strcat (thread_data[i].op_filename,".h264");
    }

    for(i=0;i<argc-1;i++)
    {
      pthread_create (&thread_id[i], NULL , &thread_function, &thread_data[i]);
    }      
}

Now in the thread function, I want to redirect stderr & stdout in one separate file as per thread. Something like a thread log file.

How can I do so?

Edit:

If thread specific prints can be displayed on different terminal..? I mean if there are 2 threads then it opens 2 terminals & prints each threads data on different terminals.

标签: c linux pthreads
5条回答
我只想做你的唯一
2楼-- · 2020-02-09 19:47

You will have to keep track of what FILE* / fd to use for each thread and use fprintf etc. There's no other way.

For multiple terminals, you need to open each terminal in your program. There's no way to automatically figure out which one to open. Run /bin/tty in the shell of the terminal you want to open, and then open that terminal in your program.

An alternative method would be to have a AF_UNIX socket listening for connections. Then you write a separate program which connects to that socket. You could run that program in the terminal where you wish output to appear.

查看更多
家丑人穷心不美
3楼-- · 2020-02-09 19:48

I don't think this is possible directly. stdin/stdout are global variables, shared between threads, and so are file descriptors.

You'll have to create your own files, and change the printf into fprintf.

查看更多
Deceive 欺骗
4楼-- · 2020-02-09 19:51

I use a fork() inside the thread for redirect the stdout of the forked process while the "true" thread is in waitpid(). The problem is how to pass the file where you want to redirect stdout. I use a global thread pool, and the thread will find itself through pthread_equal(pthread_self(),iterator), then in the global thread pool structure there is the outfile where the program should redirect the stdout. In my case I create a tmpnam() and write it to the thread struct, but you can use it how you wish.

Here is some example code: (written on the fly)

pthread_t *t_cur=NULL;
int i,pid,newout;
char *outfile=NULL;

for(i=0;i<MAX_THREADS;i++)
  if(pthread_equal(pthread_self(),globals.tpool[i]->thread))
    break;
if(i==MAX_THREADS)
{
   printf("cannot find myself into global threads pool.\n");
   pthread_exit(&i);
 }
if(globals.tpool[i]->outfile == NULL) //  redirect stdout only if outfile is not set ( this is specfic for my purposes )
{
  outfile = globals.tpool[i]->outfile = malloc(L_tmpnam*sizeof(char));
  tmpnam(outfile);
}

if((pid = fork()) == 0)
{
   if(outfile!=NULL)
   {
     newout = open(outfile,O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
     dup2(newout,STDOUT_FILENO);
     close(newout);
   }
   /* your code here */
}
else
  waitpid(pid,NULL);
pthread_exit(&i);

I really wrote it on the fly, I haven't tested this code, so take care to fix any errors. I didn't post my real code because of calls to my own library. Here I didn't check the return values from tmpnam(), fork(), open() and malloc(), which you should do.

查看更多
一夜七次
5楼-- · 2020-02-09 19:55

stdout and stderr are unique streams, by definition. Imagine, how would shell redirect your streams if there were multiple stdouts? You would need to create your own output streams/file variables and use them instead. Is there a problem with that?

You might find it useful to use thread-specific storage.


You cannot make a process output something on a different terminal. The process doesn't know about terminal, it just outputs the stream, and the terminal picks it up and displays.

What you can however do is to direct output from one of the streams into a file, and run tail -f <filename> in a different terminal.

查看更多
淡お忘
6楼-- · 2020-02-09 19:57

If you really must do this...

First you need to create 2 pthread_key_ts, one for stdout and one for stderr. These can be created using pthread_key_create, and they must be accessable from all threads. Let's call them stdout_key and stderr_key.

When a thread is being created:

FILE *err = ..., *out = ...;
pthread_setspecific(stdout_key, out);
pthread_setspecific(stderr_key, err);

and then in your header file:

#define stdout (FILE*)pthread_getspecific(stdout_key)
#define stderr (FILE*)pthread_getspecific(stderr_key)
#define printf(...) fprintf(stdout, ##__VA_ARGS__)

then just use:

fprintf(stderr, "hello\n");
fprintf(stdout, "hello\n");
printf("hello\n");

I don't recommend this approach though.

查看更多
登录 后发表回答