Okay so I am trying to teach myself on how to do signalling, and I came across a hiccup and I can't figure out what I'm doing wrong. What is going on right now is: it is executing the parent then goes to child and then back to parent.. It's not doing what I want it to do which is execute the parent (which the user defines the amount of time it runs) then kills it then go to child and run itself at the same amount of time.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h> // for wait
#include <sys/wait.h> // for wait
void action(int);
void action(int dummy){
sleep(1);
printf("Switching\n");
}
int main(int argc, char *argv[]){
pid_t pid;
int m = atoi(argv[1]), i = 0, x = 0;
if((pid=fork())>0){//parent
sleep(1);
while(i < m){
printf("hello %d\n", x);
x++;
kill(pid, SIGUSR1);
signal(SIGUSR1, action);
pause();
i++;
}
}
else
while(i < m){//child
//waitpid(getppid(), &status, 0); // wait for parent
signal(SIGUSR1, action);
pause();
printf("hi%d\n", x);
x++;
kill(getppid(), SIGUSR1);
i++;
}
}
What I want it to do is:
hello 0
hello 1
hello 2
hello 3
hello 4
Switching
hi 0
hi 1
hi 2
hi 3
hi 4
Any help is much appreciated!
You've got most of the pieces, they just need to be reordered a little bit.
install the signal handler in both processes before using kill
the parent should finish printing before signaling the child
the child can signal back after its done printing
void action(int dummy)
{
sleep(1);
printf("Switching\n");
}
int main(int argc, char *argv[])
{
int m = 3;
if (argc == 2)
m = atoi(argv[1]);
pid_t pid = fork(); // create the child process
signal(SIGUSR1, action); // set up the signal handler for both parent and child
if ( pid > 0 ) // the parent
{
for ( int i = 0; i < m; i++ )
{
sleep(1);
printf("hello %d\n", i);
}
kill( pid, SIGUSR1 ); // signal the child
pause(); // wait for the child to signal back
printf("All done\n");
}
else // the child
{
pause(); // wait for the signal from the parent
for ( int i = 0; i < m; i++ )
{
sleep(1);
printf("hi %d\n", i);
}
kill(getppid(), SIGUSR1); // signal the parent
}
}
Related
I create child using the fork and I try to kill the generated child every 3 seconds. I also try to kill my parents using "raise or kill".
I don't know how to do to kill parent processor.
When I run my code except kill parent, unlike my expectations, so many child kill come out.
that's the code :
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main()
{
int ch[3];
int i;
for (i = 0; i < 3; i++) {
ch[i] = fork();
if (ch[i] == 0){
printf("child[%d]=%d\n",i,getpid());
exit(0); }
}
for(i = 0; i<3; i++) {
sleep(3);
kill(ch[i],SIGKILL);
printf("Killch[%d]=%d\n",i,ch[i]);
}
/* KILL or raise() parent kill */
}
How can I correct this code?
sleep() is not correct solution to collect child status, use wait() or waitpid() in parent.
when parent is in sleep
for(i = 0; i<3; i++) {
sleep(3);
kill(ch[i],SIGKILL);
printf("Killch[%d]=%d\n",i,ch[i]);
}
in your code child is not waiting for parent to kill ? child is killed by itself by exit(0) statement.
You(child) need to send it's exit status to parent and parent's need to collect the child's status using wait() or waitpid() and then kill ?
If you want to observe that whether parent is killing child or not, use delay in child and observe.
"I try to kill the generated child " I ? assuming parent,Here is my code
int a[3];
int temp[3]; //to set flag=1 , when child completes instruction and become zombie
//collect status in wait() in parent, so no need to further process in my_isr
void my_isr(int n) //if child has not completed instruction, i.e not removed by wait() in parent
{ //then remove it using my_isr
printf("in isr..\n");
static int i;
for(;i<3;i++)
if((temp[i]!=1) )//if first child "not turned into zombie and removed by parent" then kill it
{
printf("child %d killed \n",i+1);
kill(a[i],SIGKILL);
}
else
{
printf("zombie child %d has been terminated normally \n",i+1);
}
}
int main()
{
if( (a[0]=fork()) == 0)
{
int r;
srand(getpid());
r=rand()%10+1;
printf("child %d is going for sleep of %d sec\n",getpid(),r);
sleep(r);
exit(1);
}
else
{
if( (a[1]=fork()) == 0)
{
int r;
srand(getpid());
r=rand()%10+1;
printf("child %d is going for sleep of %d sec\n",getpid(),r);
sleep(r);
exit(2);
}
else
{
if( (a[3]=fork()) == 0)
{
int r;
srand(getpid());
r=rand()%10+1;
printf("in child %d is going for sleep of %d sec\n",getpid(),r);
sleep(r);
exit(3);
}
else
{
int s;
printf("in parent : %d \n",getpid());
signal(SIGALRM,my_isr);
//setting timer to tell child's that you need to completes within this duration
alarm(5);
while(wait(&s) != -1)//when there is no child left , wait returns -1
{
if( s>>8 == 1 )
temp[0]=1; //set the flag when exit status is received
else if( s>>8 == 2)
temp[1]=1; //set the flag when child completed work before
else if( s>>8 ==3)
temp[2]=1; //set the flags when zombies are removed
}
}
}
}
return 0;
}
I hope it help's you.
In my following program i have two processes( the father and the child) both do the same thing but we want to figure out how will finish his task first. There is a randomized number of seconds both will sleep causing the challenge of who finishes first more random. Both are sending signals to the other process, when five signals have been recieved the process will then send a SIGTERM to the other process signaling that it has finished first. that other process will print that the opponent process has won. My problem is with sending that sigterm signal to the other process, ive tried kill function, singal function and dont know where is my mistake and what to try next. So any help would e=be appreciated below is my code:
//--------including--------------
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>
//-------global----------------
int sig1_counter=0;
int sig2_counter=0;
//-------prototypes--------------
void catch_sigusr1(int sig_num) ;
void catch_sigusr2(int sig_num) ;
void do_son() ;
void do_dad() ;
//--------main------------------
int main (){
pid_t pid;
srand((unsigned)time(NULL));
signal(SIGUSR1, catch_sigusr1) ;
signal(SIGUSR2, catch_sigusr2) ;
pid = fork() ;
switch(pid) {
case -1 : perror("fork() failed") ;
exit(EXIT_FAILURE) ;
case 0 : do_son() ;
exit(EXIT_SUCCESS) ;
default: do_dad() ;
exit(EXIT_SUCCESS) ;
}
return EXIT_SUCCESS;
}
//-------functions-------------------
void do_son() {
int i ;
for (i=0;i<10;i++)
{
int sleep_time=rand()%4;
sleep(sleep_time);
int num=rand()%2;
if (num==0)
kill(getpid(), SIGUSR1) ;
else
kill(getpid(), SIGUSR2);
}
}
//---------------------------------
void do_dad() {
int i ;
for (i=0;i<10;i++)
{
int sleep_time=rand()%4;
sleep(sleep_time);
int num=rand()%2;
if (num==0)
kill(getpid(), SIGUSR1) ;
else
kill(getpid(), SIGUSR2);
}
}
//---------------------------------
void catch_sigusr1(int sig_num) {
signal(SIGUSR1, catch_sigusr1);
printf(" process %d got signal SIGUSR1\n", getpid()) ;
if (sig_num==SIGTERM)
{
printf("process %d win\n", getpid());
exit(EXIT_SUCCESS);
}
sig1_counter++;
if (sig1_counter==5)
{
printf(" process %d surrender\n", getpid()) ;
kill(getpid(),SIGTERM); // here we have a mistake
//signal(SIGTERM,catch_sigusr2); // !!!!!!!!!!!
exit(EXIT_SUCCESS);
}
}
//---------------------------------
void catch_sigusr2(int sig_num) {
signal(SIGUSR2, catch_sigusr2) ;
printf(" process %d got signal SIGUSR2\n", getpid()) ;
if (sig_num==SIGTERM)
{
printf("process %d win\n", getpid());
exit(EXIT_SUCCESS);
}
sig2_counter++;
if (sig2_counter==5)
{
printf(" process %d surrender\n", getpid()) ;
kill(getpid(),SIGTERM);
//signal (SIGTERM,catch_sigusr1);
exit(EXIT_SUCCESS);
}
}
Both your do_son() and do_dad() functions send signals to getpid(), which means they are signalling only themselves rather than each other.
In order to signal each other, you need:
do_dad() to send the signal to pid, the return value from fork() being the child PID; and
do_son() to send the signal to getppid(), the parent PID, noting the use of non-sexist terms in the system call :-)
In other words, something like this in your main function:
switch (pid = fork()) {
case -1:
perror("fork() failed");
break;
case 0:
do_both(getppid());
break;
default:
do_both(pid);
break;
}
The reason there's no distinct parent and child function any more is that the only difference is which PID gets signalled. Because you're passing that in as a parameter, you can combine the two functions:
void do_both(pid_t other) {
for (int i = 0; i < 10; i++) {
int sleep_time = rand() % 4;
sleep(sleep_time);
if ((rand() % 2) == 0)
kill(getpid(), SIGUSR1);
else
kill(getpid(), SIGUSR2);
}
}
I need to send a signal to a child process 3 times.
The problem is that the child only receives the signal once and then transforms into a zombie.
The expected output would be:
I'm the child 11385 and i received SIGUSR1
I'm the child 11385 and i received SIGUSR1
I'm the child 11385 and i received SIGUSR1
But the real output is:
I'm the child 11385 and i received SIGUSR1
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
void my_handler()
{
printf("\n I'm the child %i and i received SIGUSR1\n", getpid());
}
int main (int argc, char **argv) {
int *array;
int N = 10;
int i;
pid_t pid1;
array=(int*)malloc(sizeof(int)*N);
signal(SIGUSR1,my_handler);
for (i = 0; i< N; i++)
{
pid1 = fork();
if(pid1 < 0)
{
exit(EXIT_FAILURE);
}
else if (pid1 > 0)
{
array[i]= pid1;
}
else
{
sleep(100);
exit(EXIT_SUCCESS);
}
}
i=0;
while(i<3) // I need to call the son 3 times
{
kill(array[1], SIGUSR1);
i++;
}
}
When the child receives the signal, it is probably waiting for the sleep to terminate. The first signal will interrupt the sleep even if the time hasn't expired, causing it to return with errno set to EINTR. If you want it to keep sleeping, you need to call sleep again.
your parent process exited without wait()ing for the child
The signals could be sent to fast, I added a short delay
i added more delays
the correct signature for a signal handler is void handler(int signum) This is crucial, because the handler is called with an argument, and the stack layout is different for signal handlers.
you should not call printf() from a signal handler, it is not async safe.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
char pidstr[10];
char massage[]=" I'm the child and i received SIGUSR1\n";
#define CNT 1
void my_handler(int signum)
{
write(0, massage, strlen(massage));
}
int main (int argc, char **argv) {
int i , err, status;
pid_t pid1;
int array[CNT];
signal(SIGUSR1, my_handler);
for (i = 0; i< CNT; i++) {
pid1 = fork();
if(pid1 < 0) { exit(EXIT_FAILURE); }
else if (pid1 > 0) {
printf("ChildPid=%d\n", pid1 );
array[i]= pid1;
}
else
{ // child
// signal(SIGUSR1, my_handler);
sprintf(pidstr,"[%d]", getpid() );
memcpy (massage,pidstr, strlen(pidstr));
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
sleep(10);
printf("Unslept\n");
exit(EXIT_SUCCESS);
}
}
sleep(10);
for (i=0; i<3; i++) {
err = kill(array[0], SIGUSR1);
printf("Err=%d:%d\n", err, (err) ? errno: 0 );
sleep(1);
}
while ( (pid1=wait( &status)) != -1){
printf("[Parent] Reaped %d\n", pid1);
}
return 0;
}
I have created a two way communication between parent and child processes using two pipes. Parent and child write data and I was able to make them read the data from each other. Parent writes numbers 1 to 5, and child writes numbers from 6 to 10. But I want parent to start reading data the first, and then reading continues in this order switching from parent to child until all the data are read: 6,1,7,2,8,3,9,4,10,5. I have tried to synchronize the reading with SIGUSR1 but when the parent is reading for the second time the program stops. I have searched a lot to find where the problem can be, and tried some tips and alike working examples, but nothing seems to help. Here is my code:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
void paction(int dummy)
{
printf("P*************************************************\n");
}
void caction(int dummy)
{
printf("C*************************************************\n");
}
int main()
{
int pfd[2];
int pfd2[2];
pid_t cfork, pfork;
if (pipe(pfd) == -1 || pipe(pfd2) == -1) {
fprintf(stderr,"Pipe failed");
exit(1);
}
cfork = fork();
signal(SIGUSR1, paction);
if (cfork == -1) {
printf("Fork Failed\n");
exit(1);
}
else if (cfork > 0) { /*parent process*/
int numbers[] = {1, 2,3, 4, 5};
int numbers2[] = { 6, 7,8, 9, 10 };
close(pfd[0]); /*close read end, write and then close write end*/
/*write part*/
int limit = 5;
int i;
for (i = 0; i < limit; i++) {
printf("Parent sends: %d\n", numbers[i]);
write(pfd[1], &numbers[i], sizeof(numbers[i]));
printf("Child sends: %d\n", numbers2[i]);
write(pfd2[1], &numbers2[i], sizeof(numbers2[i]));
}
printf("***************************************************\n");
close(pfd[1]);
close(pfd2[1]);
/*read part/////////////////////////////////////////*/
int temp;
int reads = 5;
int j;
for (j = 0; j < reads; j++) {
sleep(1);
read(pfd2[0], &temp, sizeof(temp));
printf("Parent gets: %d\n", temp);
kill(cfork, SIGUSR1);
pause();
}
/*printf("***************************************************\n");*/
kill( cfork, SIGUSR1 );
close(pfd2[0]);
}
else { /*child process*/
signal(SIGUSR1, caction);
close(pfd[1]);
int temp;
int reads = 5;
int j;
pfork = getppid();
for (j = 0; j < reads; j++) {
sleep(1);
read(pfd[0], &temp, sizeof(temp));
printf("Child gets: %d\n", temp);
kill(getppid(), SIGUSR1);
pause();
}
/*printf("***************************************************\n");*/
close(pfd[0]);
close(pfd2[0]);
}
return 0;
}
My output looks like this:
> Parent sends:1
> Child sends:6
> Parent sends:2
> Child sends:7
> Parent sends:3
> Child sends:8
> Parent sends:4
> Child sends:9
> Parent sends:5
> Child sends:10
> **************************************************************
Parent gets:6
> C************************************************************
> Child gets:1
> P*************************************************************
> Parent gets:7
And here is when it stops.
If someone can help me I would really appreciate it because I really want to know where the problem is, and since I am a beginner in C programming and processes!
Thank you in advance
printf() is not an async-safe function. Calling printf() in both normal code and a signal handler will cause undefined behavior. In particular, printf() may need to take a lock on the output-stream, while taking locks in signal-handlers is very inadvisable (risk of self-deadlock).
Maybe it is a bad idea to use signals, but I had a task in which it was assigned to use SIGUSR1. I solved the issue by adding:
static struct sigaction pact, cact;
/* set SIGUSR1 action for parent */;
pact.sa_handler = p_action;
sigaction(SIGUSR1, &pact, NULL);
After the parent was assigned the first action, it worked fine.
Thank you:)
I have some troubles:
it is not clear for me how to synchronise parent and child processes using signals, and this code doesn't work.
I thought that it should work like that: parent sends signal to child, child's pause() is end, child sends signal to parent, parent's pause() is end .. etc
why it is not so?
#include <stdlib.h>
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
void handler_cp() {
}
void handler_pc() {
}
void child_proc() {
int i = 0;
for (; i < 50; ++i) {
pause();
kill(getppid(), SIGUSR2);
}
void parent_proc(pid_t ch) {
int j = 0;
for (; j < 50; ++j) {
kill(ch, SIGUSR1);
pause();
}
}
int main(int argc, char* argv[]) {
signal(SIGUSR1, handler_cp);
signal(SIGUSR2, handler_pc);
pid_t ch = fork();
if (ch == 0)
child_proc();
else
parent_proc(ch);
return 0;
}
The signal may arrive before pause is called, in which case it will deadlock. Using signals for synchronization is, in general, a very bad idea.
In the child_proc method, reverse the lines as :
kill(getppid(),SIGUSR2);
pause();
This will wake the parent before the child goes to sleep.