Pthread in C basic print - c

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);
}

Related

How to use semaphores to control progress of 2 threads?

I learned the concept of semaphore. And I'm trying to implement it.
I've been trying to implement it for over 19 hours, but I can't do it, so I'm writing to ask for your help.
It checks the progress of the current two threads, just as it does with CV, and if both threads output entered, it can resume the subsequent operation.
Below is the full text of the code.
`
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
void *child1(void *arg) {
printf("child thread 1 entered!\n");
// call semaphoreshere here
printf("child thread 1 exits!\n");
return NULL;
}
void *child2(void *arg) {
printf("child thread 2: entered!\n");
// call semaphores here
printf("child thread 2: exits\n");
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t p1, p2;
printf("parent thread: begin\n");
// init semaphores here
// // sem_init(&empty, 0, 0);
// // sem_init(&full, 0, 0); //Code tried but not working properly
pthread_create(&p1, NULL, child1, NULL);
pthread_create(&p2, NULL, child2, NULL);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("parent thread: end\n");
return 0;
}
`
Using ONLY TWO semaphores within the code, this attempts to control the thread's internal execution order so that both threads must output the ~~entered message before it can exit.
The execution result I want is as follows.
>>>
parent thread: begin
child thread 1 entered!
child thread 2: entered!
child thread 2: exits
child thread 1 exits!
parent thread: end
>>>
parent thread: begin
child thread 2 entered!
child thread 1: entered!
child thread 1: exits
child thread 2 exits!
parent thread: end
Like this, I want to implement only the role of monitoring each other to see if they've entered.
I'd appreciate your help.
thanks.
What you want to do (in semaphoore-thinking) is:
thread 1 waits till thread 2 is done before it exits.
thread 2 waits till thread 1 is done before it exits.
Which leads to the following code, which I modified a bit because I cannot stand global variables.
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <semaphore.h>
#include <pthread.h>
#include <stdlib.h>
typedef struct SharedContext_tag {
sem_t t1done;
sem_t t2done;
} SharedContext_t;
void *child1(void* arg) {
SharedContext_t* ctx = (SharedContext_t*) arg;
printf("child thread 1: entered!\n");
sem_post(&ctx->t1done);
sem_wait(&ctx->t2done);
printf("child thread 1 exits!\n");
return NULL;
}
void *child2(void* arg) {
SharedContext_t* ctx = (SharedContext_t*) arg;
printf("child thread 2: entered!\n");
sem_post(&ctx->t2done);
sem_wait(&ctx->t1done);
printf("child thread 2: exits!\n");
return NULL;
}
int main(int argc, const char* argv[]) {
pthread_t p1;
pthread_t p2;
SharedContext_t context;
sem_init(&context.t1done, 0, 0);
sem_init(&context.t2done, 0, 0);
printf("parent thread: begin\n");
pthread_create(&p1, NULL, child1, &context);
pthread_create(&p2, NULL, child2, &context);
pthread_join(p1, NULL);
pthread_join(p2, NULL);
printf("parent thread: end\n");
sem_close(&context.t1done);
sem_close(&context.t2done);
return 0;
}
On my machine at this time (being careful here!), the output is as required:
> ./sema
parent thread: begin
child thread 1: entered!
child thread 2: entered!
child thread 2: exits!
child thread 1 exits!
parent thread: end
In order for it to work, you need to link against the real-time library, librt. You do so by adding -pthread to your compile command.
> clang-13 -g -O0 -pthread -o sema sema.c

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");.

Why Don't The Children Recive The Signal

I have a parent process that is spawning X number of child processes (player) based off the first argument passed to the program. After each child is spawned it sends them a signal. For now all I want the children to do it print they received the signal and exit, but they don't seem to get the signal from the parent. Are the children not getting the signal or am I handling it wrong?
Parent:
#define _POSIX_SOURCE
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
void reciveCard() {
write(1, "signal recived\n", 15);
exit(0);
}
int main(int argc, char **argv) {
int numPlayers, i;
int *kpids;
numPlayers = atoi(argv[1]);
kpids = malloc(numPlayers * sizeof(int));
signal(SIGUSR1, SIG_IGN);
for(i = 0; i < numPlayers; i++) {
if((kpids[i] = fork()) == 0) {
if(execlp("./player\0", "./player\0", (char *) NULL) == -1) {
printf("error\n");
exit(1);
}
}
}
for(i = 0; i < numPlayers; i++) {
printf("%d\n", kpids[i]);
kill(kpids[i], SIGUSR1);
}
wait(NULL);
return 0;
}
Child:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
void reciveCard() {
write(1, "signal recived\n", 15);
exit(0);
}
int main() {
signal(SIGUSR1, reciveCard);
while(1) {
sleep(1);
}
return 0;
}
You have a race condition.
The parent program does the fork calls so fast that it falls into the kill loop before any child has a chance to do the execlp.
Thus, the child can't set up the handler fast enough. That is, when the signal comes in, the child is still ignoring it because of the parent's SIG_IGN call that it has inherited.
Now, after the execlp, the child will set up the handler, but the signal has already occurred, so the the handler will never be called.
To see this, add a sleep(1) between the two parent loops and it should work.

tgkill kills entire process instead of just the tid passed

I have been trying to use tgkill to remotely kill a thread. I know that
pthread_kill is recommended for this kind of thing because of there not being any glibc
wrappers for tgkill but, I will be making the kill call outside of the process.
I've made a small example here to show what has been happening.
#define _GNU_SOURCE
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/syscall.h>
#define GETTID 224
void helper1(void);
void helper2(void);
int main(int argc, char *argv[])
{
pid_t process_id, thread_id;
pthread_t h1, h2;
process_id = getpid();
thread_id = syscall(GETTID);
printf("Main Thread: (PID-> %d :: TID-> %d\n", process_id, thread_id);
pthread_create(&h1, NULL, (void *) helper1, NULL);
sleep(1); // slight delay in creating each thread.
pthread_create(&h2, NULL, (void *) helper2, NULL);
printf("Entering Main's loop\n");
for (;;)
;
return 0;
}
void helper1(void)
{
pid_t process_id, thread_id;
process_id = getpid();
thread_id = syscall(GETTID);
printf("Helper1 Thread: (PID-> %d :: TID-> %d\n", process_id, thread_id);
sleep(3);
printf("Entering Helper1's loop\n");
for (;;)
;
}
void helper2(void)
{
pid_t process_id, thread_id;
process_id = getpid();
thread_id = syscall(GETTID);
printf("Helper2 Thread: (PID-> %d :: TID-> %d\n", process_id, thread_id);
sleep(3);
printf("Entering Helper2's loop\n");
for (;;)
;
}
Compiling the following after getting and passing tgid and one of the thread id's
that printed out.
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/syscall.h>
#define TGKILL 270
int main(int argc, char *argv[])
{
long ret;
int tgid, tid;
tgid = atoi(argv[1]);
tid = atoi(argv[2]);
ret = syscall(TGKILL, tgid, tid, SIGTERM);
if (ret != 0)
perror("tgkill");
return 0;
}
Calling the above passing both the tgid and tid ends with the entire process being killed instead of the expected outcome of just the tid being ended and the main process continuing to loop along.
Is this the correct outcome here and I'm just not understanding the use of tgkill or am I making some kind of error calling here?
From man pthread_kill (essentially a pthreads wrapper around the tgkill syscall):
Signal dispositions are process-wide: if a signal handler is installed, the handler will be invoked in the thread thread, but if the disposition of the signal is "stop", "continue", or "terminate", this action will affect the whole process.
The "terminate" signal is delivered to the designated thread, but the effect is to kill the entire process.

Pthread function starting in 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.

Resources