Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
573 views
in Technique[技术] by (71.8m points)

c - Unexpected output in a multithreaded program

Following is a program which uses pthreads.

#include <pthread.h> // posix threads 
#include <stdio.h>
#include <stdlib.h>

/* to compile use -lpthread */

void * sample_thread(void *);

#define MAX 10

int main() 
{
  pthread_t tid; 
  pthread_attr_t attr; 
  int k;  

  pthread_attr_init(&attr); // set default attributes 
  pthread_create(&tid, &attr, sample_thread, NULL); // create new thread
  // sample_thread will run as the new thread 

  for(k=0; k<MAX; k++) { 
    printf("Hi I'am %s %d 
",__func__,k); 
  }


  //this would kill all the threads,
}

void * sample_thread(void * p)
{ 
  int k; 
  for(k=0; k<MAX; k++) { 
    printf("Hi I'am %s %d 
",__func__,k); 
  }

}

Each time when I run the program I am expecting to get different number of execution numbers from the main thread and the child thread (because the main thread might exit before the child). I am getting this expected output sometimes. But I got an output as follows, which I am unable to understand why.

Hi I'am main 0 
Hi I'am main 1 
Hi I'am main 2 
Hi I'am main 3 
Hi I'am main 4 
Hi I'am main 5 
Hi I'am main 6 
Hi I'am main 7 
Hi I'am main 8 
Hi I'am main 9 
Hi I'am sample_thread 0 
Hi I'am sample_thread 0 
Hi I'am sample_thread 1 
Hi I'am sample_thread 2 
Hi I'am sample_thread 3 
Hi I'am sample_thread 4 
Hi I'am sample_thread 4 
Hi I'am sample_thread 5 

Why did the sample thread 0 and 4 print twice?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As highlighted by @R.. in the comments, this appears to be a bug in the implementation of glibc (assuming you are using Linux -- I can reproduce this on Linux 2.17 compiled with GCC 4.9.1), in that exit() doesn't ensure, while flushing and closing streams, there's no race when it's called by one thread when multiple threads use stdout.

The following from flockfile manual clearly indicates that the behaviour observed is not correct:

The stdio functions are thread-safe. This is achieved by assigning to each FILE object a lockcount and (if the lockcount is nonzero) an owning thread. For each library call, these functions wait until the FILE object is no longer locked by a different thread, then lock it, do the requested I/O, and unlock the object again.

In light of this, the following options can be considered as a workaround (as there's no response to the bug report) to this particular case that we observed here.


Both the threads "share" the stdout stream and I think, the "extra" output is printed because of the premature exit of main thread.

printf buffers (in sample_thread()) the output and before it could clear it's buffer (due to in printfs), main thread exits. Hence forcing the flush of stdout buffer when the process exits.

To fix,

1) you could call setbuf() in main() before creating the thread:

setbuf(stdout, NULL);

to not buffer stdout at all.

Or
2) call pthread_exit() in both threads so that the process continues if either thread dies.

Or
3) call pthread_join() in main thread so that main thread waits for the completion of sample_thread thread.

Either one of these will avoid the issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...