Segfault when dereferencing pointer set by pthread_join - c

I have the following code for testing how to "implement return values" using pthread_exit() and pthread_join().
#include <stdio.h>
#include <pthread.h>
void* busy() {
int returnValue = 2;
pthread_exit((void*)&returnValue);
}
int main() {
void* retVoidPtr = NULL;
int* retValPtr = NULL;
int retVal;
pthread_t busyThread;
pthread_create(&busyThread, NULL, busy, NULL);
pthread_join(busyThread, &retVoidPtr);
retValPtr = (int*) retVoidPtr;
retVal = *retValPtr;
printf("Busy thread returned %d\n", retVal);
return 0;
}
The program compiles fine, but never gets to the printf statement. A segfault occurs at the line retVal = *retValPtr. Using gdb, I can see that the retValPtr pointer is no longer NULL but when I try print *retValPtr gdb says "Cannot access memory at address 0x...". Any suggestions where I'm going wrong?

A C function can't return a pointer to a value on the stack under the best of circumstances. If that stack is the stack of a thread that has terminated, though, we're talking complete disaster, as the memory for that thread's stack may no longer be mapped -- that appears to be the case here.
Your thread function needs to return a pointer to data that will remain valid when the thread terminates: a global variable, or a block obtained from malloc().

Related

Simple pthread prog: segmentation fault

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.

How collect thread exit status(using join) when cancelled

I am trying to cancel thread from caller or calle, but both are crashing the program
But if I join I am getting the exit status correct.
how to collect the exit status properly on pthread_cancel
man page says below
After a canceled thread has terminated, a join with that thread using
pthread_join(3) obtains PTHREAD_CANCELED as the thread's exit status.
(Joining with a thread is the only way to know that cancellation has
completed.)
#include <stdio.h>
#include <pthread.h>
void *thread_func(void *arg);
int errNum = 3;
int main()
{
pthread_t t_id;
void *status;
// on success pthread_create return zero
if(pthread_create(&t_id,NULL,thread_func,NULL) != 0){
printf("thread creation failed\n");
return 0;
}
printf("thread created with id %u successfully\n",t_id);
// status will be collecting the pthread_exit value
// error numberis returned incase of error
// pthread_cancel(t_id);
if(pthread_join(t_id,&status) != 0){
printf("join failed\n");
}
printf("thread %u exited with code %d\n", t_id, *(int *)status);
return 0;
}
void *thread_func(void *arg)
{
printf("Inside thread_func :%u\n",pthread_self());
//the arguments of pthread_exit should not be from local space, as it will be collected in caller using join
//pthread_exit(&errNum);
// if we return it may cause seg fault as we are trying to print the value from ptr(status)
//return ;
pthread_cancel(pthread_self());
}
If a thread is cancelled (before it has terminated normally), then when you join it, you will receive PTHREAD_CANCELED as the thread's return value / exit status. That macro expands to the actual void * value that is returned, so you can compare the value you receive directly to that to judge whether the thread was cancelled. It generally is not a valid pointer, so you must not try to dereference it.
Example:
void *status;
// ...
if (pthread_join(t_id, &status) != 0) {
// pthread_join failed
} else if (status == PTHREAD_CANCELED) {
// successfully joined a thread that was cancelled
// 'status' MUST NOT be dereferenced
} else {
// successfully joined a thread that terminated normally
// whether 'status' may be dereferenced or how else it may be
// used depends on the thread
}
It is worth noting that the wording of the Linux manual page is a bit fast and loose. Threads do not have an "exit status" in the sense that processes do, and the actual POSIX specifications do not use the term in the context of threads. For example, the POSIX specifications for pthread_join() say:
On return from a successful pthread_join() call with a non-NULL value_ptr argument, the value passed to pthread_exit() by the terminating thread shall be made available in the location referenced by value_ptr.
That's a bit of a mouthful compared to the Linux wording, but it is chosen to be very precise.
Note also that the choice of type void * here is intentional and useful. It is not merely an obtuse way to package an int. Through such a pointer, a thread can provide access to an object of any type, as may be useful for communicating information about the outcome of its computations. On the other hand, it is fairly common for threads to eschew that possibility and just return NULL. But if a thread did want to provide an integer code that way, then it would most likely provide an intvalue cast to type void *, rather than a pointer to an object of type int containing the chosen value. In that case, one would obtain the value by casting back to int, not by dereferencing the pointer.

Passing a struct by value to another function initializes it to zero

I am trying to create a thread library and my thread is a struct type. Have to follow a certain interface and in that I need to pass the thread by value. For ex: to join on a thread my code is as follows:
int thread_join(thread_t thread, void **status1)
{
printf("Joining thread\n");
long int thId = thread.id;
printf("Thread id: %ld\n", thId);
gtthread_t * thrd = getThreadFromID(thId);
while(thrd->status != EXIT)
{
}
status1 = &(thrd->ret_value);
return 0;
}
And I an passing a struct of type thread_t to this function. My problem is when I see the thread's ID in the calling function, its displayed properly but when I check it in the thread_join function its displayed as 0. The caller function is as follows:
void* caller(void* arg)
{
thread_t th;
thread_create(&th, some_function, NULL);
thread_join(th, NULL);
while(1);
}
Thread create initializes the ID of the thread to a non-zero value and starts the function associated with it.
My thread structure (and other relevant structure is):
typedef enum
{
RUNNING,
WAITING,
CANCEL,
EXIT
} stat;
//Thread
typedef struct
{
ucontext_t t_ctxt;
long int id;
stat status;
void * ret_value;
int isMain;
} thread_t;
int thread_create(thread_t *thread, void *(*start_routine)(void *), void *arg)
{
thread = (thread_t *)malloc(sizeof(thread_t));
thread->id = ++count;
thread->status = RUNNING;
thread->ret_value = NULL;
thread->isMain = 0;
if(getcontext(&(thread->t_ctxt)) == -1)
handle_error("getcontext");
thread->t_ctxt.uc_stack.ss_sp = malloc(SIGSTKSZ);
thread->t_ctxt.uc_stack.ss_size = SIGSTKSZ;
thread->t_ctxt.uc_link = &sched_ctxt;
makecontext(&thread->t_ctxt, (void (*)(void))wrap_func, 2, (void (*)(void))start_routine, arg);
enqueue(gQ, thread);
printf("Thread id: %ld\n", thread->id);
swapcontext(&(curr_thread->t_ctxt),&sched_ctxt);
return 0;
}
Why does this happen? After all, I am passing by value and this should create a copy of the thread with the same values. Thanks.
EDIT:
Basically I am having a queue of threads and there is a scheduler which round-robins. I can post that code here too but I'm sure that's needless and that code works fine.
EDIT2:
I am making a header file from this code and including that header in another file to test it. All my thread_t variables are static. The caller is a function which includes my header file.
What is this line:
thread = (thread_t *)malloc(sizeof(thread_t));
for?
You pass in to thread_create() an address which referrs to a struct thread_t defined in caller() as auto variable.
Doing as you do, you allocate memory to the pointer passed in to thread_create() initialise it and forget the address on return.
The code never writes to the memory being referenced by the address passed in! Besides this it is a memory leak.
To fix this simply remove the line of code quoted above.
You have no mutex guard on thread id getter. Presumably, there is no guard on setter. What can be happening is that the variable is not visible in the other thread yet. And, without a critical section, it may never become visible.
Each variable which is accessed for both read and write from different threads has to be accessed in a critical section (pthread_mutex_lock / unlock).
Another possibility is that you are setting the thread id inside the running thread and you are accessing the variable even before it is set. If you attempt to join immediately after starting a thread it is possible, that the other thread hasn't been run at all yet and the variable is not set.
side note: do yourself a favor and use calloc:)
In caller function,
thread_create(&th, some_function, NULL);
should be
gtthread_create(&th, some_function, NULL);

Segfault occurs on initialization in pthread only

I cannot understand why the following pseudo code is causing a segfault.
Using pthreads to run a function I run into a SEGFAULT initializing an integer to zero.
When my_threaded_function not in threaded context or if I called function from the main thread there is no issue.
The SEGFAULT doesn't occur on initializing rc=0;bu only inside the maze_init function.
I have confirmed that I am out of stack space. But I can't think of what is causing the function to behave differently inside the pthread (no shared memory involved), the address &aa cannot be accessed according to gdb.
Why would a stack variable's address not be on the stack?
int maze_init(Maze*m, char* filename)
{
FILE *fp;
int aa, bb, rc;
aa = 0; /// SEGFAULT HERE
...
return 1;
}
void* my_threaded_function(void* arg)
{
Maze maze;
int rc;
rc = 0;
rc = maze_init(&maze,"test.txt");
return rc;
pthread_exit((void*)1);
}
int main(int argc,char** argv){
pthread_t t;
pthread_create(&t, NULL, my_threaded_function,(void*)0);
sleep(10);
}
edit (fixed code typo to return rc)
I have confirmed that I am out of stack space. But I can't think of
what is causing the function to behave differently inside the pthread
Well for one by default secondary threads have smaller stacks than the "main" thread. You can set the size with pthread_attr_setstacksize.
TLPI says:
Each thread has its own stack whose size is fixed when the thread is
created. On Linux/x86-32, for all threads other than the main thread,
the default size of the per-thread stack is 2 MB. The main thread has
a much larger space for stack growth
So that is one reason why it would work when called normally and fail when called from a secondary thread.

passing a local variable to thread. is it possible?

i'm working on gcc ,
i'm wondering if this is possible:
I have a function (NOTmain but aLocalFn) and I declare a local variable in it. Then I pass this local argument as a thread argument. is it doable? or there is the chance (depending on what is run first) that the aLocalVar will be lost before threadFunction is run and the reference idxPtr will be pointing to senselessness??
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
return 0;
}
thank you for your help
This code is incorrect. The function aLocalFn may return before the thread function starts executing. And so by the time the thread function reads the local variable, the scope of that variable may have ended.
What can confuse matters is that this code may very well appear to work, at least some of the time. However, it is incorrect and you should use heap allocated memory instead.
your code has a life-time issue with "aLocalVar"
if you just want to pass an integer, here is a non-portable way to do it.
it does not work on some platforms, but you are not likely to encounter those.
void threadFunction ( void * idxptr ) {
int rec_idx = (int) idxptr;
....
}
int rec_idx = returnsRecordIndex();
pthread_create (&thread1, &attr_detached, (void *) &threadFunction, (void *)rec_idx);
It's doable, but it's not done in the code in your question. You will have to add a signal variable to indicate when the new thread is done using the variable. Then your outer function can return.
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
static pthread_cond_t signal = PTHREAD_COND_INITIALIZER;
int done;
int *threadFunction(void *idxPtr){
int rec_idx=(int) *idxPtr;
pthread_mutex_lock(&lock);
done = 1;
pthread_cond_signal(&signal);
pthread_mutex_unlock(&lock);
//work in the thread with this variabel rec_idx
}
int aLocalFn(){
int aLocalVar=returnsRecordIndex();
done = 0;
pthread_create(&thread_id,&attr_detached,threadFunction, &aLocalVar)!=0)
pthread_mutex_lock(&lock);
while (!done)
pthread_cond_wait(&signal, &lock);
pthread_mutex_unlock(&lock);
return 0;
}
Note that this example code is itself not thread safe (if multiple threads call aLocalFn).
This does complicate the code, and locking is expensive. So in most cases you're probably better off storing the data in the heap and letting the new thread or pthread_join code free it.
#pizza's answer is what I'd do. Another way for you to do it would be to use malloc/free as #David hinted at. I would certainly do this over the wait loop proposed in other answers here.
int *threadFunction(void *idxPtr){
int rec_idx = *(int *)idxPtr;
// free up our int buffer
free(idxPtr);
...
}
int aLocalFn(){
int aLocalVar = returnsRecordIndex();
// allocate some space for our int
int *intBuf = (int *)malloc(sizeof(int));
*intBuf = aLocalVar;
pthread_create(&thread_id,&attr_detached,threadFunction, intBuf)!=0)
return 0;
}
Whenever you are passing variables to a thread function, it is your job to ensure that the variable remains alive and valid till the thread function is done using it.
In your case aLocalFn() continues to execute simultaneously with the new thread and may even finish execution before the thread, that leaves you with an dangling pointer(pointer pointing to data that may not exist) in thread function since the local variable aLocalVar in the function ceases to exist after function returns.

Resources