I have this code below from a book, compiled on Ubuntu 18.4, with Eclipse -O0 -g3
#include <pthread.h>
#include <stdio.h>
void *myThread( void *arg )
{
printf( "Thread %d started\n", (int)arg );
pthread_exit( arg );
}
#define MAX_THREADS 5
int main()
{
volatile int i;
int status;
int ret;
pthread_t threadIds[MAX_THREADS];
for (i = 0 ; i < MAX_THREADS ; i++) {
ret = pthread_create( &threadIds[i], NULL, myThread, (void *)i );
if (ret != 0) {
printf( "Error creating thread %d\n", (int)threadIds[i] );
}
}
for (i = 0 ; i < MAX_THREADS ; i++) {
printf("----------- i = %d\n",i);
ret = pthread_join( threadIds[i], (void **)&status );
if (ret != 0) {
printf( "Error joining thread %d\n", (int)threadIds[i] );
} else {
printf( "Status = %d\n", status );
}
}
return 0;
}
This code worked correctly and produced the output
----------- i = 0
Thread 3 started
Thread 0 started
Status = 0
----------- i = 1
Thread 2 started
Thread 1 started
Status = 1
----------- i = 2
Status = 2
----------- i = 3
Status = 3
----------- i = 4
Thread 4 started
Status = 4
However, if volatile keyword at variable i declaration is ignored, the following output is produced:
Thread 1 started
Thread 0 started
Thread 2 started
Thread 3 started
----------- i = 0
Status = 0
----------- i = 1
Status = 1
----------- i = 1
Error joining thread -947054848
----------- i = 2
Status = 2
----------- i = 1
Error joining thread -947054848
----------- i = 2
Error joining thread -955447552
----------- i = 3
Status = 3
----------- i = 1
Error joining thread -947054848
----------- i = 2
Error joining thread -955447552
----------- i = 3
Error joining thread -963840256
----------- i = 4
Thread 4 started
Status = 4
----------- i = 1
Error joining thread -947054848
----------- i = 2
Error joining thread -955447552
----------- i = 3
Error joining thread -963840256
----------- i = 4
Error joining thread -1073744128
Please help me identify what the problem could be that led to this issue.
In your code:
int status;
// ...
pthread_join( threadIds[i], (void **)&status );
this is a strict aliasing violation. The pthread_join writes a value of type void * to the location, however you provided the location of an int. This causes undefined behaviour, meaning anything can happen.
Possibly what happened on your system would be a write out of bounds (int = 4 bytes, void * = 8 bytes), scrambling the stack leading to a mess.
You can fix this with:
void *status;
// ...
pthread_join( threadIds[i], &status );
and later on, if you want to print status with %d, use (int)status for the argument.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With