6

I have written the following code using the POSIX pthread library:

#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>

pthread_t pid1,pid2;

void *test(void *arg)
{
void **end;
printf("\nNew Thread ID: 0x%x\n",(unsigned int)pid2);
pthread_join(pid1,end);
printf("\nNew Thread going to go off\n");
printf("\nNew Thread ID: 0x%x\n",(unsigned int)pid2);
return ((void *)NULL);
}    

int main()
{
pid1 = pthread_self();
pthread_create(&pid2,NULL,test,NULL);
printf("\nMain Thread ID: 0x%x\n",(unsigned int)pid1);
sleep(2);
printf("\nI am going off\n");
pthread_exit(0);
}

On executing the code I got the following output:

Main Thread ID: 0xb7880b30
New Thread ID: 0xb787eb70
I am going off
Segmentation fault

As I studied, the thread(pid2) calling the pthread_join will block until the thread passed in argument(pid1) calls pthread_exit(). And pthread_exit() is used to stop the execution of a particular thread letting all others to keep on executing.

I want to know why I got Segmentation Fault at last.

Please explain me properly.

Adriano Carneiro
  • 57,693
  • 12
  • 90
  • 123
pradeepchhetri
  • 2,899
  • 6
  • 28
  • 50
  • Usually, the child would exit, not the main application thread. Have you tried it the other way round? – forsvarir May 03 '11 at 19:24
  • Did you debug where segfault is coming from? http://www.cprogramming.com/debugging/segfaults.html – Alexander Pogrebnyak May 03 '11 at 19:26
  • pthread_join() will make the child to wait for the parent to exit first. – pradeepchhetri May 03 '11 at 19:28
  • 1
    Also note that casting `pthread_t` to `unsigned int` is bogus (and could easily result in two distinct thread ids looking the same); you should use `void *` and `%p` to print it, but even this is not 100% portable since POSIX allows `pthread_t` to be a struct/union type. And `pid1` and `pid2` are rather misleading names for variables which are not pids but rather thread ids... – R.. GitHub STOP HELPING ICE May 03 '11 at 20:30

3 Answers3

9

You're using an uninitialized variable, void **end;, which results in undefined behavior:

pthread_join(pid1,end);

What you should instead be doing is:

void *end;
pthread_join(pid1, &end);

i.e. passing a meaningful pointer to a variable in which you want the result, rather than an uninitialized pointer.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
5

I think the problem is that your end pointer passed to pthread_join()isn't actually pointing anywhere. Try the following:

void *test(void *arg)
{
    void *end;    // <===
    printf("\nNew Thread ID: 0x%x\n",(unsigned int)pid2);
    pthread_join(pid1,&end);  // <===
    printf("\nNew Thread going to go off\n");
    printf("\nNew Thread ID: 0x%x\n",(unsigned int)pid2);
    return ((void *)NULL);
}
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
1

A segmentation fault merely means that you've tried to make a memory access or jump to some location in memory that the OS hasn't allowed you to either execute code from or read/write from. In this case where is your spawned child thread suppose to return to after the pthread_join() call since the OS has cleaned up the main parent process and reclaimed the all the memory used by the main parent process (this includes execution code as well as stack-space, heap-space, etc.)? ... It's definitely not memory that a user-land thread has access to, hence the OS throws a segmentation fault.

Jason
  • 31,834
  • 7
  • 59
  • 78
  • With pthreads, `main()` can call `pthread_exit()` while other threads are left running. This is different than the Win32 threading API (I'm not sure if the Win32 pthreads port handles this or not). – Michael Burr May 03 '11 at 20:10