Parent and child proc sync using signals - c

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.

Related

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.

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

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

How to handle SIGHLD

I'm having some troubles using sigchld...
what I want to do is to create a child process with fork and make the child print and sleep a second for a couple of times... during these process I want to send signal to child (SIGSTOP and SIGCONTINUED) and I want the parent to print what the signal was... here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
void handler (int i) {
int x;
waitpid(-1,&x, 0);
printf("WIFSTOPPED=%d, WIFCONTINUED=%d\n", WIFSTOPPED(x),WIFCONTINUED(x) );
}
int main(){
int x;
int q=fork();
if(q==0){
int i=0;
printf("%d\n",getpid());
while (i<20){
printf("%d\n", i++);
sleep(1);
}
_exit(0);
}
else {
signal(SIGCHLD, handler);
waitpid(-1,&x, 0);
while(WIFEXITED(x)!=1){
waitpid(-1,&x, 0);
sleep(1);
}
exit(0);
}
}
but it doesn't work beacause when I send a SIGSTOP or SIGCONTINUED to the child, the child stop and continue but the parent doesn't print anything
any suggestion?
Your handler shall not call waitpid again and you main while loop is also not correct : again you call waitpid twice the first time. And last, your waitpid call much declare to be interested in status changes (WUNTRACED option).
A much correct code could be :
void handler (int i) { // a handler just handle the fact some signal occured
printf("in handler\n");
}
int main(){
int x;
int q=fork();
if(q==0){
int i=0;
printf("%d\n",getpid());
while (i<20){
printf("%d\n", i++);
sleep(1);
}
_exit(0);
}
else {
signal(SIGCHLD, handler); // catch child status changes
do {
waitpid(-1,&x, WUNTRACED|WCONTINUED); // wait until child terminates or changes its status
if (WIFSTOPPED(x)|WIFCONTINUED(x)) // test what really happens
printf("STOPPED=%d, CONTINUED=%d\n", WIFSTOPPED(x),WIFCONTINUED(x) );
} while(!WIFEXITED(x));
exit(0);
}
}

parent doesn't create child?

I try to create 4 child processes who will work simultaneously, but the output of my program is quite random: sometimes one of the processes is not created (the printf statement is not executed). I can not understand the reason for this, because when I use the wait() function in my parent it should wait for it's children to finish? Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#define NR_OF_PROCESSES 4
void readProcess(void);
void tokenProcess(void);
void calculatorProcess(void);
void errorProcess(void);
void (*functionTable[NR_OF_PROCESSES]) (void) = {readProcess, tokenProcess, calculatorProcess, errorProcess};
int main(void) {
int i;
int status;
for (i = 0; i < NR_OF_PROCESSES; i++) {
int pid = fork();
if (pid < 0) {
perror("could not fork");
return 0;
}
if (pid == 0) {
functionTable[i]();
exit(0);
}
}
printf("parent is waiting");
wait(status);
return (0);
}
void readProcess(void) {
printf("readprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
void tokenProcess(void) {
printf("tokenprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
void calculatorProcess(void) {
printf("calculatorprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
void errorProcess(void) {
printf("errorprocess running, PID=%d, PPID=%d\n",getpid(),getppid());
}
Also, I want to add interprocess communication with pipes later on. Will this be possible if I implement the processes this way? Any better solution?
You only wait for one child, you probably want to call wait for each child.

Resources