strange behavior of pthread_create

This is a discussion on strange behavior of pthread_create within the Linux Programming forums, part of the Platform Specific Boards category; Hi all. I'm new to this forum. I've some problem with this piece of code: Code: #define N 2 void* ...

  1. #1
    Registered User
    Join Date
    May 2010
    Posts
    26

    strange behavior of pthread_create

    Hi all. I'm new to this forum.
    I've some problem with this piece of code:

    Code:
    #define N 2
    void* handler_function(void* args) {
      int index = *((int*)args);
      printf("\n-----index = %d------\n",index);
      return NULL;
    }
    
    int main() {
      pthread_t threads[N*N];
      int i;
      for (i=0;i<N*N;i++)
        pthread_create(&(threads[i]),NULL,&handler_function,&i);
        
      for (i=0;i<N*N;i++)
        pthread_join(threads[i],NULL);
    }
    try to compile&exec it (i use posix thread so add -lpthread option to gcc command)

    my output:
    Code:
    np2k@serena:~/source/thread$ gcc -o test test.c -lpthread
    np2k@serena:~/source/thread$ ./test
    -----index = 2------
    -----index = 2------
    -----index = 0------
    -----index = 0------
    np2k@serena:~/source/thread$
    the problem is with pthread_create function. in fact, when I print the index value in the thread_function routine, I don't see all the values of index (from 0 to N*N-1).
    A tricky solution to this matter is to add a sleep(1) after pthread_create. By doing so, things work well. But I don't want to wait, obviously.

    please help me
    Last edited by np2k; 05-10-2010 at 12:39 PM.

  2. #2
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    Each thread gets the same pointer to the argument. As the loop continues, this value keeps changing out from underneath the threads.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    26
    Quote Originally Posted by brewbuck View Post
    As the loop continues, this value keeps changing out from underneath the threads.
    i don't understand...and, anyway, what could be a solution to this problem?

  4. #4
    Captain Crash brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,239
    What good is a solution when you don't understand the problem?
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    26
    Quote Originally Posted by brewbuck View Post
    What good is a solution when you don't understand the problem?
    ok, let me understand please

  6. #6
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,506
    > what could be a solution to this problem?
    6 months of background reading, research and studying.

    Here's why you shouldn't (or shouldn't yet).
    Threads Considered Harmful

    If debugging a normal application (single thread) can be scaled from 1 to 10, then making it threaded easily pushes it into the hundreds.
    If you end up with a race condition that only shows up under heavy load, then any attempt to debug it will cause the problem to go away. At that point, you're basically screwed.

    This tutorial seems pretty good
    https://computing.llnl.gov/tutorials/pthreads/

    Make no mistake, threads are a chainsaw tool. You need to be exceedingly careful about how you use it. For starters, you need a damn good plan as to what each thread is doing, what data it might be sharing and how it synchronises with the rest of the system.
    You CANNOT just hack a thread program together and hope it will work.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  7. #7
    Registered User
    Join Date
    May 2010
    Posts
    26
    yes, salem. thanks for your links...but i've studied the threads and the program that i've post has a strange behavior: i don't have understand why.

  8. #8
    Registered User Codeplug's Avatar
    Join Date
    Mar 2003
    Posts
    4,662
    >> pthread_create(&(threads[i]),NULL,&handler_function,&i);
    You are passing in the address of the variable "i". So all threads are reading i's value - which is being changed by the for-loop's "i++".

    Just pass in a copy of i's value:
    > pthread_create(&(threads[i]),NULL,&handler_function,(void*)i);

    Then:
    > int index = (int)args;

    gg

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Salem View Post
    > what could be a solution to this problem?
    6 months of background reading, research and studying.
    A lot of obfuscation and mystification of thread apparatus around. Going by some of the documentation, you would think learning to use a fairly basic technology is equivalent to being an Apollo astronaut. Then all of a sudden your VCR is working fine and you wonder what the beejesus all the fuss was about.

    Anyway, I don't use threads that much but as Codeplug indicates, you are are assuming something about when that thread is executing and what the value of i is at that point:
    Code:
      for (i=0;i<N*N;i++)
        pthread_create(&(threads[i]),NULL,&handler_function,&i);
        
      for (i=0;i<N*N;i++)  /*  OMG!!! */
        pthread_join(threads[i],NULL);
    Hopefully that wasn't too hard to explain.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,506
    Like brewbuck said, if you don't understand that &i gives shared access to a volatile location, then you're simply not ready for the rest of the dragons that lurk in the dark corners of the pthread dungeons.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    26
    Quote Originally Posted by Codeplug View Post
    >> pthread_create(&(threads[i]),NULL,&handler_function,&i);
    You are passing in the address of the variable "i". So all threads are reading i's value - which is being changed by the for-loop's "i++".
    damn it! I had missed a "silly" detail...

    but, wait...what a dirty thing! in this way, in thread_function routine I get the value of the args pointer's address which coincides with the value of i
    isn't it?

    @Salem...I know what &i gives...and even if this were so, you could not explain things well? thanks salem.......
    Last edited by np2k; 05-11-2010 at 03:31 AM.

  12. #12
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,506
    brewbuck in post #2 told you exactly what the problem was, and in post #3 you were all "huh?"

    And now you get it!?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Salem View Post
    And now you get it!?
    @Salem: Perhaps because it has been too many years since you had to deal with this "confusion" it is hard for you to recognize what might "clarify"?

    This is not to say that brewbuck did not explain "exactly what the problem was", just to raise the question of for whom.

    Quote Originally Posted by np2k View Post
    but, wait...what a dirty thing! in this way, in thread_function routine I get the value of the args pointer's address which coincides with the value of i
    isn't it?
    The address of a variable does not coincide with it's value. Passing a value is not the same as passing the address of a value. Of course, in single threaded programming the value of a variable passed by reference will not change during a function's execution. But with parallel processing, it can. Without a lock, it could even change during a read, which means all variables that are accessed by more than one thread should use a locking mechanism of some sort (such as a mutex) to ensure it is only accessed by one thread at a time.

    However, if you passed the value of i instead of it's address, then it would be a separate local stack value inside each instance of handler_function, so that would not be an issue.
    Last edited by MK27; 05-11-2010 at 11:13 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    Registered User
    Join Date
    May 2010
    Posts
    26
    Quote Originally Posted by MK27 View Post
    @Salem: Perhaps because it has been too many years since you had to deal with this "confusion" it is hard for you to recognize what might "clarify"?

    This is not to say that brewbuck did not explain "exactly what the problem was", just to raise the question of for whom.
    thanks...
    The address of a variable does not coincide with it's value. Passing a value is not the same as passing the address of a value. Of course, in single threaded programming the value of a variable passed by reference will not change during a function's execution. But with parallel processing, it can. Without a lock, it could even change during a read, which means all variables that are accessed by more than one thread should use a locking mechanism of some sort (such as a mutex) to ensure it is only accessed by one thread at a time.
    However, if you passed the value of i instead of it's address, then it would be a separate local stack value inside each instance of handler_function, so that would not be an issue.
    sorry but I have not explained well, i'm italian and my english is not good. all of your speech was clear, from long time...I said something else, but now it's no important because I clarified the question by myself. anyway thank you for your help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Strange concat bugg
    By Zarniwoop in forum C Programming
    Replies: 7
    Last Post: 05-01-2008, 09:43 PM
  2. "new" is strange
    By The Wazaa in forum C++ Programming
    Replies: 26
    Last Post: 03-06-2006, 11:32 AM
  3. Strange results using dnsapi and windns
    By Niara in forum Networking/Device Communication
    Replies: 3
    Last Post: 08-13-2005, 10:21 AM
  4. strange edffect of "fputs"
    By Abdi in forum C Programming
    Replies: 1
    Last Post: 05-04-2002, 09:41 AM
  5. bcc32 compiling error (really strange!!)
    By jester in forum C++ Programming
    Replies: 14
    Last Post: 01-26-2002, 03:00 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21