views:

51

answers:

1

Hi all,

I'm having some problems with my program in VS .NET 2003.

I initially wrote a module that uses the pthread library to create a number of threads to process something. This runs correctly in VS .NET 2003. Then this module was used by someone else and integrated into another larger program. I'm not sure about the details, but the program creates a GUI that allows the user to select an option to run my module.

When the thread is created, a value is passed in as the thread id. The problem with my module in the GUI is that the value of the thread id is 0 for all the threads, while the thread id is correct in the module without GUI.

Here's how the thread is created in the module:

int64_t *tid[1000];
int64_t i = 0, rc;

for (i = 0 ; i < NUM_THREADS ; i++)
{
   tid[i] = (int64_t *) malloc(sizeof(int64_t));
   *tid[i] = i;
   rc = pthread_create(&pthread, &attr, function, (void *)tid[i]);
   Sleep(1);
   if(rc)
   {
      free(tid[i]);
      exit(1);
   }
   free(tid[i]);
}

I checked the project properties of both, and the only differences between the 2 projects are listed below:

GUI - use managed extensions | my module (w/o GUI) - does not use managed extensions
In C/C++ preprocessor:
   GUI - WIN32;_DEBUG;_CONSOLE;WINDOWS | my module (w/o GUI) - none
In C/C++ Additional Options:
   GUI - /CLR | my module (w/o GUI) - no /CLR (error with /CLR: fatal error LNK1000: Internal error during BuildImage)

The code is the same, so I don't get why the output is wrong for the GUI, unless the use of managed extensions/clr somehow makes a difference? (I'm not really sure what those are either.)

Edited to add the part of code that outputs the thread id:

void *function(void *input)
{
   int64_t threadid = *(int64_t *)input;
   printf("threadid = %ld\n", threadid);
   ...
}

Please advise.

Thank you.

Regards, Rayne

A: 

It appears you have a race condition when passing the tid to the function - try removing the Sleep(1) and having the thread free tid instead. From your comment above, this seems to solve the issue.

To answer your other question, when pthread_create returns to your main thread, the new thread has been created (memory allocated for thread in OS, etc) but may not have actually run yet. Putting Sleep(1) makes it more likely that the new thread will run (forces main thread to give up timeslice) but there's no guarantee thread will get tid before main thread runs again and calls free(tid[i]);

Hence the idea of having the worker thread free tid - it will free after it has picked it up.

If you change your tid array to an array of int64's and pass &tid[i] then you won't need malloc/free and the race condition is also solved - though this only works if you're guaranteed to have only one caller to your library at once.

I hope this helps - getting threading right can be tricky but well worth the effort!

Sam Post