C: Signal sending to children causes infinity loop - c

I've got following problem with my code. It(children) should start counting from 0 when child process receives SIGHUP (works fine), but when parent process gets signal hup it should make all children count from 0 again, but when signal is sent then something like infinity loop happens and on_hup function for parent is called all time and doesn''t stop :( Thanks in advance.
#include <signal.h>
#include <stdio.h>
#include <wait.h>
#include <unistd.h>
#include <sys/types.h>
//#include "err.h"
#define NR_PROC 3
pid_t pid;
int a;
int pids[3];
void on_hup(int sig){
int i;
if(pid!=0)
kill(0,SIGHUP);
else
a=0;
}
void pierwsze(){
for (;a<10000;a++){
printf("%d: %d PID: %d \n",getpid(),a,pid);
fflush(stdout);
sleep(2);
}
}
struct sigaction init(){
struct sigaction sa;
sigset_t block_mask;
sigemptyset (&block_mask);
sa.sa_mask = block_mask;
sa.sa_flags=0;
sa.sa_handler=on_hup;
return sa;
}
int main(){
int i;
a=0;
struct sigaction setup_action = init();
sigaction(SIGHUP,&setup_action,0);
for(i=0;i<NR_PROC;i++){
switch(pid = fork()){
case -1:
fprintf(stderr,"Error w fork \n");
case 0:
pids[i]=getpid();
pierwsze();
return 0;
default:
printf("I am parent My PID = %d\n",getpid());
printf("fork = %d\n",pid);
}
}
while(1){}
wait(0);
return 0;
}

the array pids cannot be shared between the parent and child.
So instead of trying to put the pid into the array from the context of the child, you can insert it from the parent's context:
Code will look like:
case 0:
pierwsze();
return 0;
default:
pids[i] = pid;
printf("I am parent My PID = %d\n",getpid());
printf("fork = %d\n",pid);

Related

how can I send a signal between a child and a parent processes in linux

I have two cods the first one is for the parent which sends a signal (SIGUSER1) to the child and when the child receive it he should print that he received it.
Parent code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand(int);
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
FILE *fp1;
fp1 = fopen("cpid.txt", "w+");
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
fprintf(fp1, "%d\n", cpid);
// kill(cpid, SIGUSR1);//id, signal, send
sigset(SIGUSR2, sighand);
return 0;
}
void sighand(int the_sig){
if (the_sig == SIGUSR2){
printf("sigusr2 received");
exit(1);
}
}
Child code
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
void sighand1(int);
int main()
{
FILE *fp1;
int pid;
fp1 = fopen("cpid.txt", "r");
fscanf(fp1, "%d,", &pid);
sigset(SIGUSR1,sighand1);
while(1) {
printf("Waiting..");
sigpause(SIGUSR1);
}
return 0;
}
void sighand1(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received");
exit(1);
}
}
When I start the code it prints that the process (child) was created then when I send a signal it wont do any thing the child stuck in a loop or the wait and the parent wont do anything can any one tell me where did i go wrong in my code or logic.
Your code has several problems:
You try to pass some pid through a file, but you can use the getppid() function (get parent id)
You have some child code, but it is not called
no signal is launched
So your code can be corrected this way:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
void parent_handler(int the_sig)
{
if (the_sig == SIGUSR2){
printf("sigusr2 received in parent\n");
}
}
void child_handler(int the_sig)
{
if (the_sig == SIGUSR1){
printf("sigusr1 received in child\n");
kill(getppid(), SIGUSR2);
exit(1);
}
}
int child_function()
{
/* prepare to receive signal */
sigset(SIGUSR1,child_handler);
while(1) {
printf("Waiting..");
fflush(stdout);
/* wait for signal */
sigpause(SIGUSR1);
}
return 0;
}
int main()
{
int cpid, ppid;
ppid = getpid();
printf("My process ID is %d\n", ppid);
cpid = fork();
if ( cpid == 0 ) {
printf("I am the child => PID = %d\n", getpid());
child_function();
return 0;
}
else
printf("I am the parent => PID = %d, child ID = %d\n", getpid(), cpid);
/* child will never reach this point */
sleep(1);
/* prepare parent to received signal */
sigset(SIGUSR2, parent_handler);
/* send signal to child */
kill(cpid, SIGUSR1);
sleep(1);
return 0;
}

How to send a signal to a child several times avoiding zombie state? C language

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

synchronization between two process in c

I am trying to send signals between two child in alternative way for 100 times.
Here is my snippet of code.
here is the link to the whole question:
sending signal between two child process
But i have synchronization issue in the loop.
where is the right position to put the sigsuspend()?
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <ctype.h>
pid_t pid2;
struct sigaction act;
sigset_t mask,oldmask,temp;
void sighandler(int signum, siginfo_t *info, void *ptr)
{
printf("Received signal %d\n", signum);
printf("Signal originates from process %lu\n",
(unsigned long)info->si_pid);
pid2 = info->si_pid;
}
int main(int argc,char **argv)
{
int i,j,counter = 0,counter2 = 0;
sigemptyset(&mask);
sigemptyset(&temp);
//sigemptyset(&oldmask);
sigaddset(&mask,SIGUSR1);
//sigset_t mask;
memset(&act, 0, sizeof(act));
act.sa_sigaction = sighandler;
act.sa_flags = SA_SIGINFO;
if(sigaction(SIGUSR1, &act, NULL) == -1)
fprintf(stderr, "sigaction failed: %s\n", strerror(errno));
pid_t current, pidOther;
current = getpid();
pidOther = atol(argv[1]);
int k;
for(k = 0;k < 100;k++){
if(pidOther != 0){ // second child
kill(pidOther,SIGUSR1);
sigprocmask(SIG_BLOCK,&mask,&oldmask);
counter++;
printf("2nd child = %d sent signal to 1st child = %d signal number = %d\n",getpid(),pidOther,counter);
//sigprocmask(SIG_BLOCK,&mask,&oldmask);
sigsuspend(&temp);
}
if(pidOther == 0) // fisrt child
{
//pause();
kill(pid2,SIGUSR1);
sigprocmask(SIG_BLOCK,&mask,&oldmask); // was blank
counter++;
printf("\nj=%d 1st child = %d sent signal to 2nd child = %d signal counter = %d\n",j,getpid(),pid2,counter);
printf("test1\n");
sigsuspend(&temp); // was pause()
}
}
return 0;
}
I don't see you calling fork() anywhere. Also taking the process ID of the second process is not the way your program should know about the child process. Here's a simple example of how to use fork.
pid_t pid = fork();
if (pid == 0)
{
// executes only in child process..
// do stuff related what you need to do in child process
}
else
{
// executes only in parent process
// pid variable contains the child process's PID.
// do stuff related what you need to do in parent process
}
// runs in both parent and child.
The problem is that the first time the first child loops, pid2 is 0, so it sends the signal to every process in the process group (including itself), which means it will start looping immediately, sending signals (just) back to itself...

C synchronize processes using signal

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

Code that send signals, one of the terminals closes

I have a problem, and it is because I execute these two codes and the second one closes the terminal just when I execute it, and the first one gets blocked because of it.
First code:
#include <signal.h>
#include <pthread.h>
#include <stdio.h>
#define N 10 // Numero de plazas disponibles en total
int POcupadas;
int main(){
POcupadas = 0;
int sig;
union sigval user_sigval;
sigset_t sigset;
siginfo_t siginfo;
sigemptyset(&sigset);
sigaddset(&sigset, SIGRTMIN);
pthread_sigmask(SIG_BLOCK, &sigset, NULL);
while(1){
sig=sigwaitinfo(&sigset, &siginfo);
int pid = siginfo.si_value.sival_int;
if (sig!=-1){
if (POcupadas != N){
++POcupadas;
user_sigval.sival_int = 0;
sigqueue(pid, SIGRTMIN+1, user_sigval);
}else{
user_sigval.sival_int = 1;
sigqueue(pid, SIGRTMIN+1, user_sigval);
break;
}
}else{
printf("Error");
}
}
return 0;
}
Second Code:
#include <signal.h>
#include <stdio.h>
#include <pthread.h>
int main () {
int sig;
srand(time(NULL));
sigset_t set;
siginfo_t siginfo;
union sigval user_sigval;
int i, num;
sigemptyset(&set);
sigaddset(&set,SIGRTMIN+1);
pthread_sigmask(SIG_BLOCK, &set, NULL);
// PID
int pid = 5845;
// PID
for(i=0; i<30; i++) {
user_sigval.sival_int = getppid();
sigqueue(pid, SIGRTMIN, user_sigval);
sig=sigwaitinfo(&set, &siginfo);
if (siginfo.si_value.sival_int == 0){
printf ("Continue executing the code.\n");
}else{ // No hay sitio 1
printf ("Finish executing the code.\n");
break;
}
sleep(1);
}
return 0;
}
Why is it? What am I doing wrong?
It looks like you are doing it to yourself. Consider this excerpt of the second code:
user_sigval.sival_int = getppid();
sigqueue(pid, SIGRTMIN, user_sigval);
Now look at the central part of the first code:
sig=sigwaitinfo(&sigset, &siginfo);
int pid = siginfo.si_value.sival_int;
if (sig!=-1){
if (POcupadas != N){
++POcupadas;
user_sigval.sival_int = 0;
sigqueue(pid, SIGRTMIN+1, user_sigval);
}else{
user_sigval.sival_int = 1;
sigqueue(pid, SIGRTMIN+1, user_sigval);
break;
}
}else{
printf("Error");
}
Supposing that a process running the second code (process 2) successfully directs its signal to a process running the first code (process 1), process 1 responds by signaling the process whose PID is delivered with the signal. That is process 2's parent (refer to getppid() in the excerpt from the second code). The default disposition for a real-time signal is process termination.
You probably want process 2 to send its own PID with the signal; that is spelled getpid().

Resources