Search code examples
cprocesssignalschild-process

C forks and processes, ¿Why its necessary this?


I am studying C and I have been trying to make a simple test program. The problem is that I have a problem that is solved by a way that I dont understand. This is My program:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <signal.h>

void trat1(int s){
    signal(SIGALRM, trat1);
}
void trat2(int s){
    signal(SIGALRM, trat2);
}

int main( void ) {
    int statusHijo1, statusHijo2;
    int hijo1, hijo2;
    int hijoFinalizado, status;
    statusHijo1 =0;
    statusHijo2 = 0;

    if((hijo1 = fork()) == 0){
        /* Hijo 1 */

        printf("-- Hijo1 PID:%d | Parent PID:%d", getpid(), getppid());
        printf("\n -- Hijo1 Lanzando SIGTERM -- \n");
        while(1){
            signal(SIGALRM, trat2);
            alarm(1);
            pause();
            printf("  -- Hijo1 awaitting 1 sec.. \n");
        }
    } 
    else{
        if ( (hijo2=fork()) == 0 ) { 
            /* Hijo 2 */

                printf("++ Hijo2 PID:%d | Parent PID:%d \n", getpid(), getppid());
                signal(SIGALRM, trat2);
                alarm(5);
                pause();
                kill(hijo1, SIGKILL); 
                printf("++ Hijo2 Sending Kill signal to Hijo1\n");
                printf("++ Proceso Hijo2 terminado\n");
        } 
        else{
            /* Padre */

            do{
                hijoFinalizado = wait(&status); //El hijo finalizado es el que cambia el estado del programa
                if(hijoFinalizado == hijo1) statusHijo1 = 1;
                else if(hijoFinalizado == hijo2) statusHijo2 = 1;

            }while(!statusHijo1 || !statusHijo2);
            printf("\n** Soy el padre con PID: %d y he terminado \n", getpid());

        }   
    }

}

This program is very simple, The father is waitting for his two childs, 1 will be waitting for 5 seconds until the second one kills it.

Here the output from console:

-- Hijo1 PID:29793 | Parent PID:29792
 -- Hijo1 Lanzando SIGTERM -- 
++ Hijo2 PID:29794 | Parent PID:29792 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
++ Hijo2 Sending Kill signal to Hijo1
++ Proceso Hijo2 terminado

** Soy el padre con PID: 29792 y he terminado 

The problem is that I dont know how hijoFinalizado = wait(&status); works, becouse without it the program doesnt funct. This is what occurs without it:

-- Hijo1 PID:1547 | Parent PID:1546
 -- Hijo1 Lanzando SIGTERM -- 
++ Hijo2 PID:1548 | Parent PID:1546 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
++ Hijo2 Sending Kill signal to Hijo1
++ Proceso Hijo2 terminado

And gets stuck here.

¿Why a variable that I dont declare is the one who decides if a process has finished?

¿Why doing while( (wait(&statusHijo1)!=hijo1)&& (wait(&statusHijo2)!=hijo2) ) ; instead isnnt correct? This is what occurs doing this:

-- Hijo1 PID:1148 | Parent PID:1147
++ Hijo2 PID:1149 | Parent PID:1147 
 -- Hijo1 Lanzando SIGTERM -- 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
  -- Hijo1 awaitting 1 sec.. 
++ Hijo2 Sending Kill signal to Hijo1
++ Proceso Hijo2 terminado

And gets stuck here.

[Addition]

¿What is the real function of trat1 and trat2? I know that they are important but I dont know why.

Sorry for my English, and thanks very much.


Solution

  • Why a variable that I dont declare is the one who decides if a process has finished?

    You mean status? You do declare it; you simply don't initialize it. And that's fine, because wait doesn't read it; wait populates it. In other words, it's not an input; it's an output.

    wait waits for a child to finish. It returns the PID of the process, and it sets status to the child's exit status.

    You can use the status as follows:

    if (WIFSTOPPED(status)) {
       printf("Child killed by signal %d\.n", WSTOPSIG(status));
    }
    else if (WEXITSTATUS(status)) {
       printf("Child exited with error %d.\n", WEXITSTATUS(status));
    }
    else {
       printf("Child completed successfully.\n", WEXITSTATUS(status));
    }