Pthread function starting in C - c

I'm actually new in processes, threads, semaphores, ipc etc(shortly operating system operations on Linux)... My problem is that I compile my code and It simply gets stuck at so funny points. Processes are executed, but they can't enter their threads' function. After that, program directly ends without doing something. I really can't figure out the problem is here or everything have problem. I don't know.
#define _GNU_SOURCE
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void * function1(void *ptr)
{
printf("Function 1\n"); //!Test prints
printf("Index is %d",*((int *)ptr));
sleep(1);
pthread_exit(NULL);
}
void * function2(void *ptr)
{
printf("Function 2\n"); //!Test prints
printf("Index is %d",*((int *)ptr));
sleep(2);
pthread_exit(NULL);
}
int main(){
//...
int *index;
int i;
pid_t f;
int number_of_process=5;
pthread_t thread1, thread2;
//...
for(i=0; i<number_of_process; i++)
{
f=fork();
if(f==-1)
{
printf("Fork Error!!\n");
exit(1);
}
if(f==0) //To block child processes re-enter
{
*index = i; //I store index number for each process here. I'll need them in the thread functions
break;
}
}
/*******************PARENT PROCESS********************/
if(f!=0){
// wait for all children to exit
while (f = waitpid (-1, NULL, 0)){
if (errno == ECHILD)
break;
}
exit(0);
}
/*******************CHILD PROCESS*********************/
else{
pthread_create(&thread1,NULL,function1,(void *)index);
pthread_create(&thread2,NULL,function2,(void *)index);
}
}

Processes are executed, but they can't enter their threads' function.
After that, program directly ends without doing something.
That's because the main thread (i.e. child process created by fork()) doesn't wait for the threads to complete their execution. So it gives you the impression that the program exits without calling all pthread functions.
Use pthread_join() after creating threads:
...
pthread_create(&thread1,NULL,function1,(void *)index);
pthread_create(&thread2,NULL,function2,(void *)index);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
...
The output may be interleaved due to threads printing without any synchronization.

Related

How to join a thread which have fork in it?

Following is the case.
{
...
pthread_create(thread_id, NULL, thread_fun, NULL);
pthread_join(thread_id, NULL);
...
}
void * thread_fun(void * arg)
{
if(fork())
{
printf("In Parent\n");
pthread_exit(NULL);
}
else
{
printf("In Child\n");
pthread_exit(NULL);
}
}
How to use pthread_join() in such a way that I can wait for both child and parent process in thread?
Put all threads into endless loops and then inspect the whole program state with ps, top, htop or similar tools. You will find that the child process only has a single thread, while the parent process has (at least) two.
Now, concerning your question how to use pthread_join() to wait for the child process, you simply can't, because you can only use it to wait for threads in the same process. You could wait for the child process to terminate (waitpid()).
If the above doesn't answer your question (it's a bit unclear because you want to "wait for both child and parent process", which is where I wonder from which process' context) take a step back instead and describe on a higher level what you're trying to achieve instead. In other words, this could be a so-called "XY Problem". Do a bit of research on that term, it's a good thing to learn and understand in any case.
There's basically two ways you can do it. You can either have the child thread wait for the child process before it exits, or you can pass the PID of the child process to the parent thread so it can wait for it. Here's the first approach:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
void *thread_fun(void *arg);
int main(void) {
pthread_t thread;
pthread_create(&thread, NULL, thread_fun, NULL);
pthread_join(thread, NULL);
return 0;
}
void *thread_fun(void *arg) {
pid_t pid = fork();
if(pid) {
printf("In Parent\n");
waitpid(pid, NULL, 0);
pthread_exit(NULL);
} else {
printf("In Child\n");
exit(0);
}
}
And here's the second:
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
struct locked_pid {
sem_t sem;
pid_t pid;
};
void *thread_fun(void *arg);
int main(void) {
pthread_t thread;
struct locked_pid s;
sem_init(&s.sem, 0, 0);
pthread_create(&thread, NULL, thread_fun, &s);
sem_wait(&s.sem);
waitpid(s.pid, NULL, 0);
pthread_join(thread, NULL);
sem_destroy(&s.sem);
return 0;
}
void *thread_fun(void *arg) {
pid_t pid = fork();
if(pid) {
struct locked_pid *s = arg;
s->pid = pid;
sem_post(&s->sem);
printf("In Parent\n");
pthread_exit(NULL);
} else {
printf("In Child\n");
exit(0);
}
}
Note that the first is much simpler than the second. This is because in the second, you need a semaphore so that the parent process knows when the child PID gets written.
By the way, there's two things you should know about this code before you use it in anything important:
It doesn't have any error-checking, even though most of the functions it uses can fail.
POSIX says "If a multi-threaded process calls fork() ... the child process may only execute async-signal-safe operations until such time as one of the exec functions is called." This means that you shouldn't be doing printf("In Child\n");.

Pthread in C basic print

I'm writing a C program using Pthreads that creates a child thread. After creating the child thread, the parent thread should ouput two messages: "parent:begin" then it should print "parent:done". Same for child thread "child:begin" and "child:done". I have to make sure that the main thread prints his second message before the spawned (child) thread does. I have to following implementation but it only prints in the wrong order. I assume I should use flags. Any help would be appreciated.
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
volatile int done = 0;
void *child(void *arg) {
printf("child\n");
done = 1;
printf("child:done");
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
while (done == 0); // spin
printf("parent: end\n");
return 0;
}
If you want the parent to print done first, then you should have the child thread spin until the parent is done. (Right now the parent spins waiting for the child.) You should also use pthread_join to make sure the child is done before the main thread returns:
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
volatile int done = 0;
void *child(void *arg) {
printf("child: begin\n");
while (done == 0); // spin
printf("child: done\n");
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
printf("parent: done\n");
done = 1;
pthread_join(c, NULL);
return 0;
}
On my machine I get this output:
parent: begin
parent: done
child: begin
child: done
At the moment done is accessed without any synchronization by both threads. Proper way is to signal the child that the parent has completed printing using a conditional variable. This leads to data race.
Moreover, main() thread complete the execution before the does. In that case, the whole process will die. You can either call pthread_join() or simply exit the main thread with pthread_exit().
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
pthread_cond_t cond=PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
volatile int done = 0;
void *child(void *arg) {
printf("child\n");
pthread_mutex_lock(&mutex);
while(done == 0)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
printf("child:done");
return NULL;
}
int main(int argc, char *argv[]) {
printf("parent: begin\n");
pthread_t c;
pthread_create(&c, NULL, child, NULL); // create child
pthread_mutex_lock(&mutex);
done = 1;
printf("parent: end\n");
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}

segmentation fault in setcontext

I'm doing some test on how a scheduler schedules a waiting thread and in the process, I want to not let OS to see a waiting thread, so I kill a thread which is waiting on a lock and start it when the lock is released, I think I should save the context of the thread before exiting and restore it when I create it again. Obviously I'm doing something wrong but I can't figure it out. (I'm very new to the subject.)
this is my code so far, it generates segmentation fault with setcontext.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <ucontext.h>
ucontext_t data;
pthread_t pth;
pthread_mutex_t lock1;
void* wake_up(void* arg) {
printf("going to wake up a thread\n");
setcontext(&data);
}
void MUTEX_UNLOCK(pthread_mutex_t* lock) {
pthread_mutex_unlock(lock);
pthread_create(&pth, NULL, wake_up, NULL);
}
void MUTEX_LOCK(pthread_mutex_t* lock) {
getcontext(&data);
while(1) {
if(pthread_mutex_trylock(lock) == 0) {
printf("got the lock\n");
break;
}
else {
printf("going to exit thread\n");
pthread_exit(NULL);
}
}
}
void* routine1(void* param) {
MUTEX_LOCK(&lock1);
printf("enter any character to continue\n");
getchar();
MUTEX_UNLOCK(&lock1);
}
int main(int argc, char** argv) {
pthread_mutex_init(&lock1, 0);
pthread_t thread1[2];
int i;
for (i = 0; i < 2; i++)
pthread_create(&thread1[i], NULL, routine1, NULL);
while(1);
}
setcontext is not valid when setting the context of a thread which has exited. (The stack pointer points into a stack which has been freed.) So that's why you're getting a crash.
More in general, getcontext and setcontext are obsolete and extremely strange functions that should not be used unless you have very specific needs regarding cooperative (non-pthreads) multithreading. While you haven't described what you're trying to do, I'm 99% certain that you don't need setcontext to do it.

C Threads - Sync

I have this code, I am trying to create n threads, Do some work in each thread, and then reap each thread. If n thread is even, use detach, and if odd, use join,
When i run the program, it first prints out Successfully reaped thread, then doing working, then successfully reaped thread... looks like i have some synchronization issues
Do I even need to use Mutex?
Can anyone help me with getting everything running in the right order?
Thank you
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
pthread_mutex_t lock;
void *dowork(){
//Do whatever needs to be done in each thread here
pthread_mutex_lock(&lock);
long tid = (long) pthread_self();
printf("Doing Work ...for %ld\n",tid);
pthread_mutex_unlock(&lock);
//pthread_exit(NULL);
return;
}
void spawn(int n){
if (pthread_mutex_init(&lock, NULL) != 0)
{
printf("\n mutex init failed\n");
exit (1);
}
int i=0;
//pthread_t * thread = malloc(sizeof(pthread_t)*n);
pthread_t threads[n];
while (i<n) {
if(pthread_create(&(threads[i]), NULL, dowork, NULL) != 0){
printf ("Create pthread error!\n");
exit (1);
}
i++;
}//End of while
// Wait for threads to complete //
i = 0;
while (i<n)
{
int success = -1;
if(i%2 == 0){
success=pthread_detach(threads[i]);
}
else{
success=pthread_join(threads[i], NULL);
}
if(success==0)
printf("Succesfully reaped thread\n");
i++;
}
pthread_mutex_destroy(&lock);
}
int main() {
spawn(5);
}

Cancelling a pthread and printf behaviour

Here is a code sample of pthread cancellation:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *my_routine(void *arg) {
int i;
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
return NULL;
}
int main(void) {
pthread_t thread;
if (pthread_create(&thread, NULL, my_routine, NULL)) {
fprintf(stderr, "Cannot create pthread\n");
return 1;
}
usleep(20);
pthread_cancel(thread);
pthread_join(thread, NULL);
//fflush(stdout);
sleep(1);
return 0;
}
I compile with:
gcc -pthread -Wall threadtest.c -o threadtest
When executing, sometimes, it prints an additional number after sleep(1).
Sometimes this number is a duplicate:
0
1
2
3
4
4 // printed after sleep(1)
Sometimes not:
0
1
2
3
4
5 // printed after sleep(1)
If I fflush(stdout) before sleep(1), then the additional number is printed immediately.
How can I avoid this weird printf behaviour when cancelling a thread?
Thank you.
You could disable cancellation while doing the printf() and add an explicit cancellation point:
int cancel_state = 0;
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cancel_state);
printf("%d\n", i);
pthread_setcancelstate(cancel_state);
pthread_testcancel();
(error checking left out for the sake of readability)
When using pthread_cancel you should take more care on thread handler.
man page of pthread_cancel explain lot about this.
man pthread_cancel
Check the example program available in the man page
When thread handler start you have to make PTHREAD_CANCEL_DISABLE with the help of pthread_setcancelstate system call, when handler meet the cancellation point set PTHREAD_CANCEL_ENABLE.
In the main check the pthread_cancel success or not with the help of PTHREAD_CANCELED macro.
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
void *my_routine(void *arg) {
int i;
//pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
for (i = 0; i < 10; i++) {
sleep(1);
printf("%d\n", i);
}
//pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
sleep(60);
return NULL;
}
int main(void)
{
pthread_t thread;
if (pthread_create(&thread, NULL, my_routine, NULL)) {
fprintf(stderr, "Cannot create pthread\n");
return 1;
}
usleep(20);
pthread_cancel(thread);
pthread_join(thread, NULL);
//fflush(stdout);
sleep(1);
return 0;
}
Initially compile and run the above program, note the output. It may not display anything and terminate the program because after thread created thread handler will wait 1sec and sleep, in that time parent thread will cancel the thread and finish process.
Then uncomment the two pthread_setcancelstate() from above program, now compile and run the program. It will now display from 1 to 9. Because thread is set as PTHREAD_CANCEL_DISABLE so parent pthread_cancel will not cancel and wait for PTHREAD_CANCEL_ENABLE.When thread handler meet PTHREAD_CANCEL_ENABLE parent thread will cancel the thread.
when you note the output. handler will not stay on sleep(60), because before that parent will cancel the thread.

Resources