1

I used to get a trouble with pthread_exit(). I know there is no way to use pthread_exit() in a way like

pthread_exit(&some_local_variable);

We always need to use pthread_exit() like:

pthread_exit("Thread Exit Message or something necessary information");

I once coded a simple program for testing purpose. I made four thread functions for addition, subtraction, multiplication and division of two integers, respectively. Then while performing these operations on four different threads, I tried to return the result of the operation by pthread_exit(). What I mean is something like:

pthread_exit(&add_result);

When I ran the code in CentOS 6, I got the desired result (i.e., garbage values from all the threads) as pthread_exit() cannot be used like that. But, I got confused. Because for the first time, I ran that code in Ubuntu 11.10 and got three absolutely correct result(correct result of the operation) from three threads and garbage value from one thread. This confused me because why three threads are giving correct result of operation?

Moreover, I used different sleep times for those threads. I found that the thread having least sleep time gave the garbage value.

As gcc is the compiler for both these operating systems, why one system has bugs like this? It confuses novice programmers like me. If it is not a bug, can anyone explain it to me why is this happening?

rr_ovi
  • 283
  • 4
  • 14
  • 4
    The fact that something works doesn't mean that it's correct... :) – Manlio Apr 05 '12 at 11:20
  • 1
    Just one note. You don't *always* have to return string constants. You can, for example `malloc ()` some memory, store a value there, and return the `malloc`'d pointer. The point is: Return **any** address that remains valid after the thread exits. – ArjunShankar Apr 05 '12 at 11:27
  • Thanks. I should got that before. – rr_ovi Apr 06 '12 at 11:54

3 Answers3

4

I think your answer is in pthread_exit doc. You say that you returned a pointer on add_result, which seems to be a local variable.

Here is the quote of the doc that might answer:

After a thread has terminated, the result of access to local (auto) variables of the thread is undefined. Thus, references to local variables of the exiting thread should not be used for the pthread_exit() value_ptr parameter value.

You may use the void* argument to the threaded function to use a structure, which should contain the actual result of your operation.

Aif
  • 11,015
  • 1
  • 30
  • 44
  • Thanks for the answer. I did not think that way. But my main concern was about why two systems behaved differently. This should not be happened. Or if happens, why? – rr_ovi Apr 05 '12 at 11:34
  • Did you try it multiple times on the ubuntu system? Maybe 1. this was context dependant 2. implementation dependant – Aif Apr 05 '12 at 11:35
  • Thanks.. I tried for several times. Even at my office, I showed it in a presentation. May be it is implementation dependent. When only one thread is used, I get the desired result. But when I use four, I got the situation stated. – rr_ovi Apr 06 '12 at 11:52
3

pthread_exit just takes a pointer to a void. If you pass the address of a variable local to the thread, sometimes that memory will have been reused for something else. Sometimes it will still be there. There's no guarantee that after a thread exits, some part of the system will go and make sure that all of the memory it was using is set to garbage values.

It's not a bug - the system is doing exactly what you ask it.

Bonus related answer - Can a local variable's memory be accessed outside its scope?

Community
  • 1
  • 1
dsolimano
  • 8,870
  • 3
  • 48
  • 63
  • 1
    You might also want to mention that not only you can get correct OR garbage values, but the program can also crash (because you accessed a memory location that you shouldn't): i.e. 'undefined behavior'. – ArjunShankar Apr 05 '12 at 11:26
1

The only requirement for pthread_exit(foo) is that foo points to something which lives long enough. Local variables don't, malloc'ed memory does.

MSalters
  • 173,980
  • 10
  • 155
  • 350