Can somebody please explain why the following loop for thread creation fails without the sleep function call?
for(t=0; t<NUM_THREADS; t++) {
printf("Main: creating thread %d\n", t);
rc = pthread_create(&thread[t], NULL, BusyWork, (void *)&t);
sleep(1);
if (rc) {
perror("pthread_create");
exit(EXIT_FAILURE);
}
}
If sleep is not inserted then thread function seems to take as an argument
an arbitrary integer between 0 ad NUM_THREADS.
I'm running this on an Ubuntu machine.
Because you are passing t as a pointer, then change t after creating the thread. So each thread refers to the same variable. Which also is a great candidate for race condition bugs. Simply don't do that.
Instead create a hard copy per thread:
type* tmp = malloc(sizeof(t));
memcpy(tmp, &t, sizeof(t));
pthread_create(&thread[t], NULL, BusyWork, tmp);
...
void* BusyWork (void* arg)
{
...
free(arg);
}
You're passing the same pointer to each thread, but still expecting each to see different values, which is not how things work.
I don't think it's a good idea to let the main program end without doing anything to collect/join the threads back together, either.
Related
The point of threads is to be able to run multiple blocks of code at once. The first thing I think of when this possibility comes into my head is having two infinite loops running at once. Before I tried to get this working with two threads, I tried to get it to work with one, with no success.
So I have a thread like this:
void *myThread(void *args) {
sleep(0.1);
while (1) {
}
return NULL;
}
And I am creating the thread like so:
pthread_t thread_id;
printf("Before Thread\n");
pthread_create(&thread_id, NULL, myThread, args);
pthread_join(thread_id, NULL);
printf("After Thread\n");
When I run this, "After Thread" does not print! Why is this happening? This makes no sense to me.
Because pthread_join(thread_id, NULL); waits for the thread to finish. And a thread running a while (1) {} loop will never finish.
My command line tool keeps throwing the bus error: 10 message. Xcode debugger shows EXC_BAD_ACCESS message and highlights the function call that creates the thread. Manual debugging shows that the execution flow breaks at random positions inside the thread flow. I tried another compiler (gcc), but it ended up the same. Disabling pthread_mutex_lock() and pthread_mutex_unlock() doesn't help. I wrote this small example that reproduces the error.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
typedef struct thread_args {
pthread_mutex_t* mutex;
} thread_args;
void* test(void* t_args) {
printf("Thread initiated\n");
thread_args* args = (thread_args* )t_args;
printf("Args casted\n");
pthread_mutex_lock(args->mutex);
printf("Mutex locked\n");
pthread_mutex_unlock(args->mutex);
printf("Mutex unlocked\n");
pthread_exit(NULL);
}
int main() {
pthread_mutex_t mutex1;
pthread_mutex_init(&mutex1, NULL);
thread_args args;
args.mutex = &mutex1;
pthread_t* thread;
printf("Initiating a thread\n");
pthread_create(thread, NULL, test, &args);
return(0);
}
I think, in your case,
pthread_create(thread, NULL, test, &args);
at this call, thread is a pointer and not allocated memory. So, essentially pthread_create() tries to write into uninitialized memory, which creates undefined behavior.
Referring the man page of pthread_create()
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread;....
Instead, you can do
pthread_t thread;
...
pthread_create(&thread, NULL, test, &args);
You're using an uninitialized pointer to your pthread_t. The actual storage of the pthread_t needs to be somewhere!
Try :
int main() {
pthread_mutex_t mutex1;
pthread_mutex_init(&mutex1, NULL);
thread_args args;
args.mutex = &mutex1;
pthread_t thread;
printf("Initiating a thread\n");
pthread_create(&thread, NULL, test, &args);
return(0);
}
As other answers pointed out, you need to initialize your pointer thread which you can simply do with:
pthread_t thread;
pthread_create(&thread, NULL, test, &args);
Well, then I'll have to allocate memory dynamically, because different
threads are spawned inside many different functions, hence I can't use
local variables, because I'm not going to join the threads. Then, how
can I free the allocated memory without waiting for the thread to
finish, i.e. without calling join?
No. You don't need to dynamically allocate just because you are going to spawn multiple threads. The thread identifier is no longer needed once a thread has been created So whether it's a local variable or malloced is not important. It's only needed when you need to join or change some characteristics of the thread -- for which you need the ID. Otherwise, you can even reuse the same thread for creating multiple threads. For example,
pthread_t thread;
for( i = 0; i<8; i++)
pthread_create(&thread, NULL, thread_func, NULL);
is perfectly fine. A thread can always get its own ID by calling pthread_self() if needed. But you can't pass a local variable mutex1 to thread functions as once main thread exits, the mutex1 no longer exits as thread created continues to use it. So you either need malloc mutex1 or make it a global variable.
Another thing to do is that if you decide to let the main thread exit then you should call pthread_exit(). Otherwise, when the main thread exits (either by calling exit or simply return) then the whole process will die, meaning, all the threads will die too.
Hi I am trying to make 3 thread that will print different messages multiple times. Then sync them, so to print for example ONE TWO THREE ONE TWO THREE ONE TWO THREE... When I run the program sometimes it is not correct and I am not sure what I am doing wrong.
sem_t sema, semb, semc;
void *printone(void *arg)
{
printf("<ONE>");
sem_wait(&semc);
sem_post(&semb);
}
void *printtwo(void *arg)
{
printf("<TWO>");
sem_wait(&sema);
sem_post(&semc);
}
void *printthree(void *arg)
{
printf("<THREE>");
sem_wait(&semb);
sem_post(&sema);
}
main()
{
pthread_t th1,th2,th3;
int i;
sem_init(&sema,0,1);
sem_init(&semb,0,0);
sem_init(&semc,0,0);
for(i=0;i<10;i++){
pthread_create( &th1, NULL, printone, (void *) 1);
pthread_create( &th2, NULL, printtwo, (void *) 2);
pthread_create( &th3, NULL, printthree, (void *) 3);
pthread_join(th1, NULL);
pthread_join(th2, NULL);
pthread_join(th3, NULL);
}
pthread_exit(NULL);
}
You seem to have a workable approach: each thread waits on one semaphore, and later posts another to let the next thread run. For that to work, however, each thread should wait for its semaphore before performing its work (i.e. print its message).
Additionally, it looks like your thread functions are using the wrong semaphores. For printone() to run first, it must wait on the semaphore that you initialize with value 1. For printtwo() to run next, it must wait on whichever semaphore printone() posts to. Similarly, for printthree().
As a secondary matter, if your thread functions are not going to use their argument, then it would be best to pass NULL as the third argument to pthread_create().
I have an issue with threads.
I am defining a global variable, a char * that I initialize to NULL, and a mutex.
pthread_mutex_t mutex;
char *minURLTime;
minURLTime = NULL;
Then I initialize my mutex:
pthread_mutex_init(&mutex, NULL);
I then create a new thread:
void *status;
pthread_t t;
pthread_create(&t, NULL, executeThread, (void *) &val);
pthread_join(t, &status);
And inside that function I allocate space for minURLTime using strdup and copy a string from link:
pthread_mutex_lock(&mutex);
minURLTime = strdup(link);
pthread_mutex_unlock(&mutex);
As I am using the heap (through strdup, which calls malloc), I do not understand why minURLTime is not NULL until the thread is exited, but then it is NULL.
pthread_exit(NULL);
Once pthread_exit is called, although minURLTime is a global variable that was allocated through strdup (which calls malloc), it appears to be NULL. I don't understand, could anyone please explain me?
Thank you very much,
EDIT:
A little more detail.
From main():
void *status;
pthread_t t;
pthread_create(&t, NULL, executeThread, (void *) &val);
pthread_join(t, &status);
ExecuteThread function:
void *
executeThread( void *val )
{
executeRequest(*((int *) val));
if (minURLTime != NULL) {
pthread_mutex_lock(&mutex);
fprintf(stderr, "\nURL AFTER THREAD ( BEFORE EXIT ): %s\n", minURLTime); // Not executed
pthread_mutex_unlock(&mutex);
}
pthread_exit(NULL);
}
fprintf does not get executed (BEFORE returning pthread_exit).
executeRequest Function:
void
executeRequest( int val )
{
/* some code */
pthread_mutex_lock(&mutex);
minURLTime = strdup(link);
pthread_mutex_unlock(&mutex);
if (minURLTime != NULL) {
pthread_mutex_lock(&mutex);
fprintf(stderr, "\nURL: %s\n", minURLTime); // This one DOES print
pthread_mutex_unlock(&mutex);
}
}
This may be helpful. It prints inside executeRequest, but not inside executeThread, before the thread exited.
Jary
You aren't waiting in the main thread for the new thread to complete, so you're seeing the null before the thread gets around to setting something else. Also, since you haven't protected the variable with a lock, or declared it volatile, the compiler might even have optimized out noticing that the thread changed it.
My apologies, I realize what the problem was, it was something inside executeRequest that was messing up with those variables, I really don't know how it could have overwritten exactly THAT part of memory, but it is fixed. Thank you and sorry!
am trying to get my head around the following:
Have a small program am trying to port to OSX(intel) which calls function doWork()
via pthread_create, in the function, I start by creating an array of long like such:
long myarray[DIMENSION]
on OSX, for the following values of DIMENSION, I get the following:
0->65434 = fine
65435->67037 = SIGBUS
67037+ = SIGSEGV
I'm totally confused here, I understand that SIGBUS is due to memory alignment issues usually, I checked sizeof(long) and it appears to be 8 on this platform. Can somebody point me in the right direction of docs I should be reading here?
Here is the source:
#include pthread.h
#include stdio.h
#define NUM_THREADS 5
#define DIMENSION 12345
void *doStuff(void *threadid)
{
long array[DIMENSION];
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t lt NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, doStuff, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
It would appear you're overflowing the stack.
You'll need to either turn the long array into a malloced one, or use pthread_attr_setstacksize and friends to create a larger stack when you call pthread_create.
Default thread stack sizes vary a lot between platforms, which would explain why the code works on other platforms.
Example code:
pthread_attr_t attr;
size_t stacksize;
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &stacksize);
printf("Default stack size = %li\n", stacksize);
stacksize = <....>;
printf("Amount of stack needed per thread = %li\n",stacksize);
pthread_attr_setstacksize(&attr, stacksize);
rc = pthread_create(&thread, &attr, dowork, (void *)t);
(code originally from https://github.com/LLNL/HPC-Tutorials/blob/main/posix/stack_management.md )
As to why you get a sigbus, it's probably because the act of creating the array is overwriting some part of pthreads internal data structures with garbage, resulting in an alignment error when pthreads tries to clean up the thread.