7

I am new to threading. Here if I comment pthread_join( thread1, NULL) then in the output sometimes I get

    Thread2
    Thread1
    Thread1

I am not able to understand why Thread1 trace is coming twice and what is the exact functionality of pthread_join.

Also, please refer some tutorial on threading concepts for beginners.

    void *print_message_function( void *ptr );
    main()
    {
            pthread_t thread1, thread2;
            char *message1 = "Thread 1";
            char *message2 = "Thread 2";
            int  iret1, iret2;
            iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);
            iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
            pthread_join( thread1, NULL);

            pthread_join( thread2, NULL); 

            printf("Thread 1 returns: %d\n",iret1);
            printf("Thread 2 returns: %d\n",iret2);
            exit(0);
    }

    void *print_message_function( void *ptr )
    {
            char *message;
            message = (char *) ptr;
            printf("%s \n", message);
    }
Kundan Kumar
  • 1,974
  • 7
  • 32
  • 54
  • Just to confirm that I can reproduce this on CentOS 6.2 using gcc 4.4.6. Nice puzzle! (+1) – NPE Apr 25 '12 at 19:55
  • My gcc version is 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) Thread model: posix – Kundan Kumar Apr 25 '12 at 19:58
  • Can't reproduce with `gcc version 4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) Thread model: posix`. – user703016 Apr 25 '12 at 20:11
  • 2
    Does it make a difference if you build using the `-pthread` option instead of using `-lpthread`? I'm wondering if the mysterious `-D_REENTRANT` option makes a difference in how the `printf()` calls are handled. I wouldn't think so, but you never know... – Michael Burr Apr 25 '12 at 20:12
  • Just tested, I can't reproduce with `-lpthread` (see my previous comment), but can with `-pthread`. Nice find @MichaelBurr – user703016 Apr 25 '12 at 20:14
  • @Soohjun: that's exactly the opposite of what I would have expected (if it made a difference at all). – Michael Burr Apr 25 '12 at 20:16
  • I was just about to suggest locking up the printf() with a mutex, just to see.. – Martin James Apr 25 '12 at 20:16
  • 1
    Are you getting a newline between the two prints of Thread 1? Because on my system they are printed on the same line. – Tudor Apr 25 '12 at 20:32
  • @Tudor...ya I was getting the output on two different lines – Kundan Kumar Apr 25 '12 at 20:39
  • are you getting anything else printed after this (like `Thread 1 returns: 0`) or just the output lines that you have shown? – Gabriel Southern Apr 25 '12 at 22:12
  • @Gabriel....I am getting this after commenting the last two printf's – Kundan Kumar Apr 25 '12 at 22:26
  • @KundanKumar I can't reproduce it on my system so I can't test any ideas that I have about why this is happening. One thing you might want to try is changing `exit(0)` to `pthread_exit(0)`. Also one guess I had about why this is happening is because you are sharing data through the stack, which might change state when the `main` thread exits. But without being able to reproduce this myself I can't figure out if my guess is correct or not. – Gabriel Southern Apr 25 '12 at 22:35
  • @Gabriel...have you tried after commenting last two printf statement ? – Kundan Kumar Apr 25 '12 at 22:37
  • @KundanKumar, yes when I do that I only get `Thread2` printed. I don't have the problem of `Thread1` printing twice, which is the interesting part of this question because that should not happen. – Gabriel Southern Apr 25 '12 at 22:47
  • @Gabriel...actually that will be reproduced if you run the program several times....may be around 10-15 – Kundan Kumar Apr 25 '12 at 22:48
  • 1
    @Gabriel: regarding sharing data through the stack - I'm not sure I see what you're referring to. The data passed to the threads are pointers to string literals, which are statically allocated so have no ties to the lifetime of `main()` (other than the lifetime of the process as a whole). – Michael Burr Apr 25 '12 at 23:04
  • @MichaelBurr that's a good point I did not think about the fact that the strings will be statically allocated. – Gabriel Southern Apr 25 '12 at 23:25
  • 1
    The thread function does not return anything. The lack of return value in non-void function may cause strange behavior in some situations. Did you try to add `return SomeValue;` to `print_message_function()`? – Pavel Zhuravlev Apr 26 '12 at 01:39
  • @Kundan: Is the problem solved or still facing the same thing? If not solved did you try out the answer i posted? Please share the result.. thanks – Sandeep Apr 27 '12 at 07:12
  • @happy2Help...on modifying the code in the way you suggested the output is proper and expected...still I just needed some explanation to my question ... i mean the nature of the output ..why thread1 was being printed twice – Kundan Kumar Apr 29 '12 at 14:20

2 Answers2

1

Perhaps the output buffer is not flushing correctly. I've encountered a very similar issue when doing multithreading and piping the output to a file--sometimes output would appear twice. Try adding this line to your main function:

setvbuf(stdout, NULL, _IONBF, 0);

This will force the output buffer to be flushed on each write.

wlformyd
  • 237
  • 2
  • 12
1

If I am getting these results, first of all I would do the following:

1) Instead of below lines,

iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);

iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);
pthread_join( thread1, NULL);

pthread_join( thread2, NULL); 

replace it with,

iret1 = pthread_create( &thread1, NULL, print_message_function, (void*) message1);

pthread_join( thread1, NULL);
iret2 = pthread_create( &thread2, NULL, print_message_function, (void*) message2);

pthread_join( thread2, NULL); 

and see what is the result.

2) Inside your thread function, you need to call pthread_exit("Exit"); This is a proper way to exit from the thread function. Do it at the end of function.

void *print_message_function( void *ptr )
{
        char *message;
        message = (char *) ptr;
        printf("%s \n", message);
        pthread_exit("Exit"); 
    }

If you are doing it this way, ideally you should not face any problem. In every case, i am assuming you are compiling your program using gcc -D_REENTRANT -o threadex threadex.c -lpthread

This is not the final solution. If it is going well, then we can proceed to next step of starting both the threads at a time.

Please share the feedback after incorporating these changes.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Sandeep
  • 18,356
  • 16
  • 68
  • 108