I am just trying to work with multi-threaded programs, but I am having problems with the pthread_join function. The code below is just a simple program I am using to show pthread_join crashing. The output from this code will be:
before create
child thread
after create
Segmentation fault (core dumped)
What causes pthread_join to give a segmentation fault?
#include <pthread.h>
#include <stdio.h>
void * dostuff() {
printf("child thread\n");
return NULL;
}
int main() {
pthread_t p1;
printf("before create\n");
pthread_create(&p1, NULL, dostuff(), NULL);
printf("after create\n");
pthread_join(p1, NULL);
printf("joined\n");
return 0;
}
Because in your call to pthread_create you actually call the function, and as it returns NULL pthread_create will fail. This will not properly initialize p1 and so will (probably) cause undefined behavior in the pthread_join call.
To fix this pass the function pointer to the pthread_create call, do not call it:
pthread_create(&p1, NULL, dostuff, NULL);
/* No parantehsis --------^^^^^^^ */
This should also teach you to check the return values of function calls, as pthread_create will return non-zero on failure.
You need to fix your function type and the way you call pthread_create:
void * dostuff(void *) { /* ... */ }
// ^^^^^^
pthread_create(&p1, NULL, dostuff, NULL);
// ^^^^^^^
Related
Trying to see how pthread works by running a simple program but I am getting segmentation fault (core dumped) at pthread_create
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* testfunc(void* arg) {
while (1) {
printf("testfunc");
}
}
int main(void) {
printf("helo\n");
if (pthread_create(NULL, NULL, &testfunc, NULL) != 0) {
perror("pthread failed to create\n");
}
while (1) {
printf("main function\n");
sleep(1000);
}
return 0;
}
What seems to be causing the problem? I am on Ubuntu 20.04 if that matters.
You can't pass NULL for pthread_create's first argument.
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread
Also, pthread_create doesn't set errno, so using perror makes no sense, at least not without some prep.
on error, it returns an error number, and the contents of *thread are undefined.
Fixed:
pthread_t thread;
if ( ( errno = pthread_create(&thread, NULL, &testfunc, NULL) ) != 0 ) {
perror("pthread failed to create\n");
}
...
pthread_join(thread, ...); // Normally.
Threads in c are very unforgiving. There are a few problems with your code that I can see.
First you might want to refer to the developer docs for p_thread. They are very well documented. What you currently have is a thread call but you are not pointing anything to that thread. This is why you are receiving the segmentation error. Meaning your program lost the pointer to that thread somewhere when it tried calling it. I suggest something like.
pthread_t thread;
int * argument = 5;
if(pthread_create(&thread,NULL, &testfunc, &argument) !=0){
// ^This is a pointer to your argument
// that you want to pass in
perror("pthread failed to create\n");
exit(1);
}
and your thread function will also need to be typecast from a void pointer into whatever you want it to return to work with. Then it needs to be cast back to a void pointer before is returned from the thread routine.
void* testfunc(void* arg){
int* testVar = (int *)arg;
// do some logic here
return (void *) testVar;
}
lastly you are responsible for your memory in C so you must kill the thread you created before exiting.
pthread_join(thread, NULL);
My number one suggestion is you watch some videos relating to it.
#include <stdio.h>
#include <pthread.h>
void* thread(void *v) {
printf("The thread starts now\n");
//pthread_exit(NULL);
}
int main() {
int tid1;
int retValue = 0;
pthread_create(&tid1, NULL,thread, NULL);
retValue = pthread_join(tid1, NULL);
printf("Thread ID: %d, return value: %d\n",tid1, retValue);
retValue = pthread_join(tid1, NULL);
printf("Thread ID: %d, return value: %d\n",tid1, retValue);
return 0;
}
Sometimes the output is:
Thread ID: 1877241856, return value: 3
Thread ID: 1877241856, return value: 3
The thread starts now
Process finished with exit code 0
The question is:
By definition, pthread_join should block, wait for thread to finish executing, and then execute code that follows it. But why in my code, thread runs after the two pthread_join finish?
By definition, pthread_join returns 0 to indicate successful joining, but why the retValue of my code is always 3, whether thread runs before or after the pthread_join function?
There are a number of bugs in this code:
The first argument of pthread_create() should be a pthread_t, not an int. They are quite possibly not the same size, or otherwise interchangeable, so tid1 might not be a valid pthread id.
The thread does not return 0, or any other value for that matter. There is no return statement.
"On success, pthread_join() returns 0; on error, it returns an error number."
The thread's return value, if there was one, would be placed into the unused 2nd argument of pthread_join(). What is being treated as the return value is in fact the result of the pthread_join() call itself. Which is an error. Perhaps it is related to #1 above?
In addition to those found by TrentP worst bug of all is
Joining with a thread that has previously been joined results in undefined behavior.
i.e. calling pthread_join twice on the same thread
retValue = pthread_join(tid1, NULL);
retValue = pthread_join(tid1, NULL);
Is utterly wrong and saying it works if you change tid1 to pthread_t is wrong. The behaviour being undefined means that anything can happen when pthread_join is called the second time - pthread_join can return an error, pthread_join can return success, it can crash, it can hang, it can modify some other parts of memory, it can cause a new thread to be started...
So I know that you can create barriers in C to control the flow of a threaded program. You can initialize the barrier, have your threads use it, and then destroy it. However, I am unsure whether or not the same barrier can be reused (say if it were in a loop). Or must you use a new barrier for a second wait point? As an example, is the below code correct (reusing the same barrier)?
#include <pthread.h>
pthread_barrier_t barrier;
void* thread_func (void *not_used) {
//some code
pthread_barrier_wait(&barrier);
//some more code
pthread_barrier_wait(&barrier);
//even more code
}
int main() {
pthread_barrier_init (&barrier, NULL, 2);
pthread_t tid[2];
pthread_create (&tid[0], NULL, thread_func, NULL);
pthread_create (&tid[1], NULL, thread_func, NULL);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
pthread_barrier_destroy(&barrier);
}
Yes, they are reusable. The man page says:
When the required number of threads have called pthread_barrier_wait()...the barrier shall be
reset to the state it had as a result of the most recent
pthread_barrier_init() function that referenced it.
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.
I'm having trouble understanding the pthread_join() function because of the results I am getting.
If pthread_join() is supposed to pause the calling thread until the thread of the given thread id finishes it's job then why does the following code not do Thread 1 work first then do Thread 2 work. They are both happening concurrently.
If I take out the two pthread_join() lines (from main) the program terminates and nothing happens. Does this mean the main thread is the calling process of both join functions and it is the main thread who is waiting for the other two newly created threads to finish?
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void *functionCount1();
void *functionCount2(void*);
int main()
{
/*
How to Compile
gcc -c foo
gcc -pthread -o foo foo.o
*/
printf("\n\n");
int rc;
pthread_t thread1, thread2;
/* Create two thread --I took out error checking for clarity*/
pthread_create( &thread1, NULL, &functionCount1, NULL)
pthread_create( &thread2, NULL, &functionCount2, &thread1)
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
printf("\n\n");
exit(0);
}
void *functionCount1()
{
printf("\nFunction 1");
sleep(5);
printf("\nFunction 1");
return(NULL);
}
void *functionCount2(void* argument)
{
//pthread_t* threadID = (pthread_t*) argument;
//pthread_join(*threadID, NULL);
printf("\nFunction 2");
sleep(5);
printf("\nFunction 2");
return(NULL);
}
Output:
Output with sleep commented out:
Can someone explain why pthread_join is not doing what the documentation leads you to believe?
if pthread_join() is supposed to pause the calling process until the thread of the given thread id finishes it's job...
That is not quite correct: pthread_join() is supposed to pause the calling thread, not the calling process. Since you are calling pthread_join() from the thread running your main function, the other two threads are allowed to proceed concurrently, i.e. the way they do in your example.
The reason the code that you commented out does not work is that you are passing a pointer to pthread_t, but then you cast it to plain pthread_t inside the thread running function (i.e. pthread_t* becomes pthread_t). Fixing this problem should allow your code to produce the results that you expect:
void *functionCount2(void* argument)
{
pthread_t *threadID = (pthread_t*) argument;
pthread_join(*threadID, NULL);
printf("\nFunction 2");
sleep(5);
printf("\nFunction 2");
return(NULL);
}
In addition, you should remove pthread_join( thread1, NULL); from your main function, because the results of multiple simultaneous calls to pthread_join() specifying the same target thread are undefined.