Reputation: 23
I'm studying thread programming. While doing below example, I got undefined behavior.
static void* print_thread_attr (void* param)
{
pthread_attr_t attr;
int detach_state = PTHREAD_CREATE_JOINABLE;
pthread_getattr_np (pthread_self(), &attr);
pthread_attr_getdetachstate (&attr, &detach_state);
pthread_attr_destroy (&attr);
printf("Detach state of thread [%u] pid [%d] is %s\n", pthread_self(), getpid(),
(PTHREAD_CREATE_JOINABLE == detach_state)?
"JOINABLE THREAD":"DETACHED THREAD");
return NULL;
}
void test_thread_attributes ()
{
pthread_t thread_id1;
pthread_t thread_id2;
pthread_attr_t attr;
printf("main pid [%d]\n", getpid());
pthread_attr_init (&attr);
pthread_create (&thread_id1, &attr, print_thread_attr, NULL);
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread_id2, &attr, print_thread_attr, NULL);
pthread_attr_destroy (&attr);
pthread_join (thread_id1, NULL);
//sleep (1);
}
1.Sometimes, it will print:
main pid [3394]
Detach state of thread [88292160] pid [3394] is DETACHED THREAD
Detach state of thread [75705152] pid [3394] is JOINABLE THREAD
But sometimes
main pid [3403]
Detach state of thread [75705152] pid [3403] is JOINABLE THREAD
Detach state of thread [88292160] pid [3403] is DETACHED THREAD
Detach state of thread [88292160] pid [3403] is DETACHED THREAD
It's strange as I use pthread_create only 2 times, but 2nd case prints 3 times. While using valgrind to check, there's no memory leak in first case, but for the second case, there's "possibly lost: 136 bytes in 1 blocks"
I need to know why in 2nd case, thread 88292160 prints twice? In addition, you may notice commented-out sleep (1). When I do sleep (1), I don't observe 2nd case happen.
Upvotes: 2
Views: 116
Reputation: 121347
You have undefined behaviour since you are calling pthread_attr_init() twice and second time with on an object initialized already:
Calling pthread_attr_init() on a thread attributes object that has already been initialized results in undefined behavior.
The object attr
can be reused if it was destroyed:
Once a thread attributes object has been destroyed, it can be reinitialized using pthread_attr_init(). Any other use of a destroyed thread attributes object has undefined results.
However, there's no guarantee in your code that the attribute will be destroyed by first thread before it can be re-initialized by the second thread. So you could use two different attribute objects or even re-use the same attribute (without re-initializing). However, since you destroy the attribute in the thread, this option is not possible at it is in your code.
The latest POSIX standard however, removed the reference undefined behaviour for re-initializing an already initialized but destroyed attribute and states:
If an implementation detects that the value specified by the attr argument to pthread_attr_init() refers to an already initialized thread attributes object, it is recommended that the function should fail and report an [EBUSY] error.
I am assuming your implementation is using a bit older and results in undefined behaviour. In any case, this is an issue and you should check return value of the pthread functions for errors.
The actual issue of duplicate outputs seen is due to an implementation issue with the stdio which is explained in an answer here which would explain why sleep
seems to "fix" the problem and and possible workarounds to avoid this problem.
Upvotes: 1