Issue with muilti-threading with pthread: thread is executing prematurely - c

I am trying to call make a thread to another function in a function being ran by a child process. I am starting by calling a child process, which makes another child process, which in turn makes a thread. However, the thread function keeps executing prematurely. What could be the issue?
#define _GNU_SOURCE
#include <sched.h>
#include <pthread.h> // pthread
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>// waitpid
#include <sys/wait.h> //waitpid
#define STACK_Size 1024*1024
void* print(void* ptr)
{
printf("\n4. In thread\n");
char* message;
message = (char*)ptr;
printf("\n5. Message from parent: %s \n\n",message);
}
static int threading(void * ptr)
{
char* message;
message = (char*)ptr;
printf("\n3. In child process 2\n");
pthread_t Tid;
pthread_create(&Tid,NULL,&print,(void*)message);
pthread_join(Tid,NULL);
printf("\n6. Thread done.... exiting child process 2\n\n");
}
static int child(void *ptr)
{
char* message;
message = (char*) ptr;
print("\n2. In child 1");
// creating child process
char* stack_ptr = malloc(STACK_Size);
unsigned long flags =0;
pid_t pid;
pid = clone(threading, stack_ptr+STACK_Size,flags | SIGCHLD,message);
int status;
waitpid(pid,&status,0);
printf("7. Done with child 2\n\n8. Now exiting child process 1\n");
}
int main(int argc, char ** argv)
{
char msg[150];
printf("1. Currently in main program name: %s\n", argv[0]);
sprintf(msg,"The name of the program is (%s), P.S this is parent (pid:%d)",argv[0],getpid());
char* stack_pointer = malloc(STACK_Size);
unsigned long flags =0;
setbuf(stdout,NULL);
if((argc >1) && (strcmp(argv[1],"vm")==0))
{
flags = CLONE_VM;
}
pid_t pid;
pid = clone(child,stack_pointer+STACK_Size,flags | SIGCHLD,msg);
int status;
waitpid(pid,&status,0);
printf("\n9. Done with Parent process\n");
}
Here is the output it's producing:
1. Currently in main program name: ./clone
4. In thread
5. Message from parent:
2. In child 1
3. In child process 2
4. In thread
5. Message from parent: The name of the program is (./clone), P.S this is parent (pid:15159)
6. Thread done.... exiting child process 2
7. Done with child 2
8. Now exiting child process 1
9. Done with Parent process

If what you mean by executing prematurely is the lines containing 4. and 5. being printed before 2., it's because you call your custom print() function to output 2. (print("\n2. In child 1")) which also prints out 4. and 5..

Related

Print exit order of child processes

I have this code. My aim is to create 'n' child processes from parent process and print the pid of each child processes once it is created.
Then I'll ask each child process to sleep for random duration using rand_r function and exit. I want to print the exit order of child processes i.e I want to print their pids in their exit order.
This is my C code. It is not giving required output:
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int func(int n)
{
if(n==0){return 0;}
int pid=fork();
unsigned int k=n;
int x=rand_r(&k) % 3;
//printf("here: %d\n", x);
if(pid==0){
printf("Child %d is created\n",getpid());
func(n-1);
sleep(x);
printf("Child %d exited\n",getpid());
exit(0);
}
return 1;
}
int main(int argc, char *argv[]){
char *inp = argv[1];
int n = atoi(inp);
func(n);
return 0;
}
I want output like this:
Child 7432 is created
Child 7433 is created
Child 7434 is created
Child 7435 is created
Child 7433 exited
Child 7432 exited
Child 7435 exited
Child 7434 exited

Semaphore not working properly

I am working on an assignment where we need to use semaphores in order to make the second print of the parent process wait until child executes first. It is first time using semaphores and I certainly understood how they work, however I think I have a problem with the initialising of sem_open().
By following this:
sem_t *sem_open(const char *name, int oflag);
I have created this:
sem_t *sem = sem_open("MYSEM", O_CREAT , 2);
However, when executing my sem_wait are ignored.This is my whole program:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
/* void ChildProcess(void) ChildProcess prototype */
/* void ParentProcess(void) ParentProcess prototype */
int main(int argc, char ** argv){
int pid;
pid = fork();
sem_t *sem = sem_open("MYSEM", O_CREAT , 2);
if (pid<0)
{
printf("Cannot create a child process");
exit(EXIT_FAILURE);
}
else if (pid==0)
{
printf("I am the child process. \n");
printf("The child process is done. \n");
sem_post(sem);
exit(EXIT_SUCCESS);
}
else
{
printf("I am the parent process. \n");
sem_wait(sem);
printf("The parent process is done. \n");
}
sem_destroy(sem);
exit (EXIT_SUCCESS);
}
and what is printing is:
I am the parent process.
The parent process is done.
I am the child process.
The child process is done.
and what should print is this:
I am the parent process.
I am the child process.
The child process is done.
The parent process is done.
in the parent : you create a semaphore, print a message and then wait for the semaphore.
in the child : you create a semaphore, print 2 messages, close the semaphone and exit.
now the parent can return from the wait.
See http://man7.org/linux/man-pages/man3/sem_wait.3.html for a trivial example

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

Cant read messages from processes using multiple pipes in c

Im creating pipes for multiple children. The code catches a signal fro the keyboard and then the child should sent a message to the father with its result. The handling of the signal works fine but i cant sent the result to the father. I am i doing something wrong here?
The code of the father process is :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
pid_t *childs; //array for storing childs pids
int number_of_childs;//variable for the number of childs
int exit_count=0;
int *fd;
/*Handler for the SIGINT signal*/
void control_handler(int sig)
{
if (sig==SIGINT){
int j,bytes;
char message[512];
/*Sending SIGUSR1*/
for (j=0;j<number_of_childs;j++)
{
kill(childs[j],SIGUSR1);
}
/*Reading from PIPES*/
for (j=0;j<number_of_childs;j++)
{
close(fd[(2*j)+1]);
bytes = read(fd[(2*j)], message, sizeof(message));
printf("Read from: %s\n",message);
close(fd[2*j]);
}
}
if (sig==SIGUSR2)
{
exit_count++;
}
}
main (int argc,char *argv[]){
int i,child_status;
char cast[512];
char cast2[512];
char cast3[512];
int pid;
number_of_childs=atoi(argv[1]);
signal(SIGINT,control_handler);
signal(SIGUSR2,control_handler);
/*Creating array for children pipes*/
fd=(int*)malloc((2*number_of_childs)*sizeof(int));
/*array that holds the pids for every child used in sending signals*/
childs=malloc(number_of_childs*sizeof (pid_t));
for (i=0;i<number_of_childs;i++){
pid=fork();
/*Create pipes to communicate with all children*/
if(pipe(fd+(2*i))==-1)
{
perror("pipe");exit(1);
}
/*Fathers code goes here*/
if(pid!=0)
{
printf("Parent process: PID= %d,PPID=%d, CPID=%d \n",getpid(),getppid(),pid);
childs[i]=pid; // Keep all your childs in an array
printf("Child:%d\n",childs[i]);
}
/*If you are a child*/
else
{
/*Change the code for the childs and set the time of execution*/
sprintf(cast,"%d",i+1); // make the time char
sprintf(cast2,"%d",(2*i)+1); //make the pipe char
sprintf(cast3,"%d",number_of_childs);
execl("./Child.out","",cast,cast2,cast3,NULL);
}
}
/*Father should never terminate*/
while (exit_count!=number_of_childs);
printf("Father pospastex!!\n");
}
the code for the child children is :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
#include <time.h>
#include <string.h>
#define WRITE 0
#define READ 1
/*Global declerations*/
int alarmflag=0;
double result=0;
int count=0;
int global_pipe;
int *fd;
/*Handler for the alarm and SIGUSR1 signal*/
void signal_handler (int sig)
{
if(sig==SIGALRM)
{
printf("Im child with pid:%d im going to die my value is %lf \n",getpid(),result);
alarmflag=1;
}
if(sig==SIGUSR1)
{
count++;
char message[512];
if(count==1)
{
close(fd[global_pipe-1]);
sprintf(message,"%d,%lf",getpid(),result);
write(fd[global_pipe],message,strlen(message)+1);
close(fd[global_pipe]);
//printf("PID:%d report: %lf\n",getpid(),result);
}
if(count==2)
{
close(fd[global_pipe-1]);
sprintf(message,"%d,%lf",getpid(),result);
write(fd[global_pipe],message,strlen(message)+1);
close(fd[global_pipe]);
//printf("PID:%d report2 : %lf\n",getpid(),result);
//kill(getppid(),SIGUSR2);
//exit(0);
}
}
if(sig==SIGINT)
{
/*Do nothing*/
}
}
double p_calculation ()
{
int i=2;
result=3;
double prosimo=-1;
while(!alarmflag)
{
prosimo=prosimo*(-1);
result=result+(prosimo*(4/((double)i*((double)i+1)*((double)i+2))));
i=i+2;
}
}
main(int argc,char *argv[])
{
int pipe;
int size_fd;
size_fd=(atoi(argv[3]));
pipe=(atoi(argv[2]));
global_pipe=pipe;
fd=(int*)malloc(size_fd*sizeof(int));
/*handling signals*/
signal(SIGALRM,signal_handler);
signal(SIGUSR1,signal_handler);
signal(SIGINT,signal_handler);
/*Notify for execution time*/
printf("PID : %d with PPID : %d executing for %d seconds \n",getpid(),getppid(),atoi(argv[1]));
//printf("pipe:%d\n",pipe);
/*end this after the value passed as argument*/
alarm(atoi(argv[1]));
p_calculation();
/*Notify for finish*/
printf("Done!!!\n");
}
There are a number of problems related to your pipes:
you call pipe AFTER you call fork, so you end up with two independent pipes (one in the child and one in the parent). The parent listens to the one it creates (and noone is writing to), so it never sees anything.
you pass the index in your global fd array to the child rather than the file descriptor of the pipe. The child has its own global fd array that contains random garbage, so you are essentially writing to a random file descriptor rather than the pipe.
you don't close the unneeded pipe ends in the various processes they exist in, so you cna never reliably get EOFs
If you search for pipe+child here on stackoverflow, you'll see a large number of questions with example code trying to do things similar to what you are doing -- you may find it useful to read through those questions and answers.

Handling processes in C

I have a problem when trying to handle a SIGUSR1 signal sent from a father process to all of his child's process. The handler on the child's does nothing. I checked for the result of the kill command and it returns 0 meaning that the message sent was ok . Can anyone help with this? Below is the code of the child process. I use execl to differ the childs code from the father. Note that the handler works well for alarm calls
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
/*Global declerations*/
int alarmflag=0;
double result=0;
int fd[2];
/*Handler for the alarm and SIGUSR1 signal*/
void signal_handler (int sig)
{
printf("******************");
if(sig==SIGALRM)
{
printf("Im child with pid:%d im going to die my value is %lf \n",getpid(),result);
alarmflag=1;
}
if(sig==SIGUSR1)
{
printf("gotit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}
}
double p_calculation ()
{
int i=2;
result=3;
double prosimo=-1;
while(!alarmflag)
{
prosimo=prosimo*(-1);
result=result+(prosimo*(4/((double)i*((double)i+1)*((double)i+2))));
i=i+2;
}
}
main(int argc,char *argv[])
{
int fd[2];
/*handling signals*/
signal(SIGALRM,signal_handler);
signal(SIGUSR1,signal_handler);
/*Notify for execution time*/
printf("PID : %d with PPID : %d executing for %d seconds \n",getpid(),getppid(),atoi(argv[1]));
/*end this after the value passed as argument*/
alarm(atoi(argv[1]));
p_calculation();
/*Notify for finish*/
printf("Done!!!\n");
}
The code for the father follows :
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/types.h>
pid_t *childs; //array for storing childs pids
int number_of_childs;//variable for the number of childs
int count_controls=0;
/*Handler for the SIGINT signal*/
void control_handler(int sig)
{
int j;
for (j=0;j<number_of_childs;j++)
{
kill(childs[j],SIGUSR1);
}
}
main (int argc,char *argv[]){
int i,child_status;
int fd[2];
char cast[512];
int pid;
number_of_childs=atoi(argv[1]);
signal(SIGINT,control_handler);
childs=malloc(number_of_childs*sizeof (pid_t));
if(pipe(fd)==-1)
{
perror("pipe");exit(1);
}
for (i=0;i<number_of_childs;i++){
pid=fork();
/*Create pipes to communicate with all children*/
/*Fathers code goes here*/
if(pid!=0)
{
printf("Parent process: PID= %d,PPID=%d, CPID=%d \n",getpid(),getppid(),pid);
childs[i]=pid; // Keep all your childs in an array
printf("Child:%d\n",childs[i]);
}
/*If you are a child*/
else
{
/*Change the code for the childs and set the time of execution*/
sprintf(cast,"%d",i+1);
execl("./Child.out","",cast,NULL);
}
}
/*Father should never terminate*/
while (1);
}
I cant see a problem with a child when I kill it from shell:
test]$ ./a.out 120
PID : 7406 with PPID : 7035 executing for 120 seconds
******************gotit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
******************Im child with pid:7406 im going to die my value is -nan
Done!!!
and parent being killed with INT does kill children with USR1:
test]$ ./a.out 1 30
Parent process: PID= 7490,PPID=7035, CPID=7491
Child:7491
PID : 7491 with PPID : 7490 executing for 40 seconds
******************gotit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
My problem is when i use control -c to the father process. It gets the
interrupt but the message from the handler that the child got the
message does not appear – Giannos 9 mins ago
The problem is that you get SIGINT in your child process.
Try to add a handler for SIGINT in the child, then run your test.
You can see what happens with your current implementation after you pressed ctrl-c:
serge 7685 7035 99 08:01 pts/3 00:00:08 ./a.out 1
serge 7686 7685 30 08:01 pts/3 00:00:02 [Child.out] <defunct>
Your child process got SIGINT and terminated. Also, it is necessary to handle the SIGCLD in the parent to get rid of all your children processes in a defunct state:
if (sig == SIGCLD)
{
// harvest terminated DEFUNCT child process
pid = waitpid(-1, &status, WNOHANG);
}

Resources