0

Could any explain me the output of the following programs (compiled using gcc (GCC) 4.6.3 version in linux) :

void * thread_routine (void *p)  
{  
    printf("Inside thread : Hello World!\n");  
    pthread_exit(NULL);  
}  

int main ()  
{  
    // Object to hold thread ID  
    pthread_t thread;  
    int rv,*exit;  
    // Routine shell create a new thread  
    rv = pthread_create(&thread, NULL, thread_routine, NULL);  
    if(rv)  
        puts("Failed to create thread");  
    printf("Exit Main\n");  
    return 0;  
}    

Output:

Exit Main
Inside thread : Hello World!
Inside thread : Hello World!

I was thinking thread_routine() will not get a chance to scheduled before which main will return. But output was different. Even if thread_routine is getting scheduled, it should print Inside thread : Hello World! once. But it is printing it twice.

If I add pthread_self() in printf statement inside thread_routine(), this thread is not getting scheduled, and in this case output is:

Exit Main
WedaPashi
  • 3,561
  • 26
  • 42
vijayanand1231
  • 447
  • 1
  • 7
  • 20
  • 1
    On success, pthread_create() returns 0, so your `if` should be `if(rv!=0)` – sjsam Apr 23 '16 at 10:59
  • 1
    Though this has no bearing to your problem – sjsam Apr 23 '16 at 10:59
  • 2
    "I was thinking thread_routine() will not get a chance to scheduled before which main will return". That is not a valid assumption. Unless you explicitly add in synchronization code to sequence the execution order the result is non-deterministic (as you have found) and depends on the OS scheduler. Can't explain why the thread print would show twice though. – kaylum Apr 23 '16 at 11:00
  • thread_routine is likely getting scheduled in both cases. However, once the main thread exits, results are unpredictable. In the first case, apparently the result is the message is output twice. In the second case, apparently thread_routine exits after calling pthread_self(), perhaps because it finds out the main thread has exited, resulting in no output from that thread. – Warren Dew Apr 23 '16 at 11:06
  • Your thread function only runs once, what _looks_ like it's happening is that `exit()` flushing all stdio streams (or possibly dealing with an i/o related atexit handler) interferes with your output from the other thread. If you really want an exact answer, it's a pretty deep rabbit hole to go into. If you replace `return 0` (ie exit) with a pthread_exit for the main thread, the problem goes away. – Joachim Isaksson Apr 23 '16 at 11:22
  • 2
    `printf()` uses a shared resource: `stdout`. Concurrent access to shared resources should be protected, which the code does not. – alk Apr 23 '16 at 11:34
  • @sjsam : the return value of pthread_create() is int type. – vijayanand1231 Apr 23 '16 at 12:31
  • @vijayanand1231: I didn't say anything about the type. But `pthread_create()` returns zero on success and so will every posix compliant function if I recall correctly. See [this](https://www.gnu.org/software/libc/manual/html_node/Exit-Status.html) – sjsam Apr 23 '16 at 12:37
  • @alk: `printf()` is thread-safe. `exit()` is not. – EOF Apr 23 '16 at 13:30
  • @EOF: `printf()` is but `stdout` isn't. – alk Apr 23 '16 at 13:32
  • @alk: Hence "`exit()` is not [threadsafe]". You can call `printf()` in multiple threads unsynchronized all day, every day, but you must not call `exit()` (or, equivalently, return from the initial invokation of `main()`) while there are multiple threads executing. – EOF Apr 23 '16 at 13:34
  • @EOF: I saw some awfully scrambled log files which had been spoiled by threads concurrently writing to it without additional synchronisation. – alk Apr 23 '16 at 13:35
  • 1
    @alk: C11 draft standard n1570, *7.21.2 Streams 7 Each stream has an associated lock that is used to prevent data races when multiple threads of execution access a stream, and to restrict the interleaving of stream operations performed by multiple threads. Only one thread may hold this lock at a time. The lock is reentrant: a single thread may hold the lock multiple times at a given time.* – EOF Apr 23 '16 at 13:37
  • @EOF Uhm, interesting, indeed! I wonder if this was in the Standards prior to C11? – alk Apr 23 '16 at 13:38
  • 1
    @alk There were no threads at all before C11, so I doubt it. Edit: At least C99 draft standard n1256 doesn't include the passage. – EOF Apr 23 '16 at 13:38
  • @EOF: You are right, I just checked the C99 document, and some rough pattern search for your quote did not reveal anything like this. Thanks for pointing me to this **significant** change. :-) One trap less to step into ... – alk Apr 23 '16 at 13:41
  • @sjsam: that if condition is for pthread_create() failure check. Not for success case. – vijayanand1231 Apr 23 '16 at 15:58
  • @vijayanand1231 : Sorry that we were not able to reach a consensus on this. – sjsam Apr 23 '16 at 16:04
  • @sjsam: Are you quite sure you understand what `if(rv)` does? – EOF Apr 23 '16 at 17:14
  • @EOF :May be I am not. Zero is returned if `pthread_create` is successful. This is what I understood from the man page. Then the op does `if(rv) puts("Failed to create thread");` which didn't make any sense to me. – sjsam Apr 23 '16 at 17:35
  • Which part do you now understand? If `pthread_create()` fails, it returns non-zero, so `rv` will be non-zero. `if(rv){puts(...);` will execute the `puts()`, because `rv` compares unequal to zero. – EOF Apr 23 '16 at 17:39
  • @EOF : Thanks for that .. Well that was me a bit whiter than usual. I didn't think of the what it will return on failure. – sjsam Apr 23 '16 at 18:08
  • @vijayanand1231 : My mistake ! I got you now.. – sjsam Apr 23 '16 at 18:09

0 Answers0