signalsforkkillalarm

task for set alarm with using fork()


I'm doing task which is Signal Communication with Separate Alarms and Parent-to-Child Signal. but i got a question about the output i got.

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

void child_handler (int signum){
        printf("Child  (PID=%d) alarm went off\n", getpid());
        // send signal to parent
        kill( getppid(), SIGUSR1 ); 
        exit(EXIT_SUCCESS);
    }
    
void parent_handler (int signum){
        printf("Parent (PID=%d) received SIGUSR1 from child after child's alarm\n", getppid());
    }
    
void user2 (int signum){
        printf("Parent (PID=%d) alarm went off\n", getppid());
        printf("Parent (PID=%d) sending SIGUSR2 to my child %d\n", getppid(), getpid());
        kill( getpid(), SIGUSR2 );
        exit(EXIT_SUCCESS);
    }
    
int main(){
        int pid;
        int status;
        
        // 1.The parent process forks a child process.
        pid = fork();
        
        if (pid == 0){
            // child process
            printf("Child  (PID=%d) setting my alarm to 3 and then wait via pause()\n", getpid());
            signal(SIGALRM, child_handler);
            alarm(3);
            pause();
            // 2. The child process sets an alarm for 3 seconds and waits for the SIGALRM signal.
        } else if (pid > 0){
            // parent process
            printf("Parent (PID=%d) preparing waiting for SIGUSR1 via pause()\n", getppid());
            
            signal(SIGUSR1, parent_handler);
            pause();     
        
            // 5.The parent process sets an alarm for 5 seconds and waits for its SIGALRM signal.
            printf("Parent (PID=%d) Setting alarm for 5 seconds and wait via pause()\n", getppid());
            signal(SIGALRM, user2);
            alarm(5);
            pause();
    
            //waitpid(pid, &status, 0);
                
            
        } else {
            // error 
            perror("Failed to fork child process.\n");
            exit(EXIT_FAILURE);
        }
        return 0;
}

so this the code and output came out like below.

Parent (PID=15925) preparing waiting for SIGUSR1 via pause()
Child  (PID=22732) setting my alarm to 3 and then wait via pause()
Child  (PID=22732) alarm went off
Parent (PID=15925) received SIGUSR1 from child after child's alarm
Parent (PID=15925) Setting alarm for 5 seconds and wait via pause()
Parent (PID=15925) alarm went off
Parent (PID=15925) sending SIGUSR2 to my child 22731
User defined signal 2

in the output, i got two questions in there. for the last sentence 'Parent (PID=15925) sending SIGUSR2 to my child 22731', i used getppid() for Parent pid and used getpid() for child pid in user2 function. but why child's pid came out differently? according to the above, seems it should be 22732, but it came out 22731.

and I was wondering why that 'User defined signal 2' message is showing up at the bottom (since I'm not printing it anywhere).


Solution

  • You're getting the "User defined signal 2" because you don't have a signal handler registered for SIGUSR2.

    As for why you're seeing the different PID, I think you have a little confusion as to how getppid() and getpid() work. getppid() returns the PID of the parent process. Now, it's important to note that "parent" here is always relative to the currently running process, which I think is where the confusion is.

    Look at the following snippet.

    ...
    pid = fork();
    
    if (pid == 0) {
        // Child process, we'll call this region B
    } else if (pid > 0) {
        // Parent process, we'll call this region A
    } else {
       // Parent process, region A
    }
    ...
    

    For this, we'll call the larger program this snippet belongs to "program Y", and the instance of the program "process Y".

    Consider the following: We have a running process X with PID 1234. Let's say that process X runs program Y, and process Y is given a PID of 1235. Let's also say that when process Y does fork(), the child's PID is 1236. Given that synopsis, we have the following.

    If we apply this to your program, we can figure out why getpid() is returning 22731.

    When the user2 function runs, that function is running as part of the parent process. getpid() will thus return the PID of the parent process, and getppid() will return the PID of the parent of the parent (i.e. the process that resulted in a call to main).

    Given the output, it looks like the PID of the process that called your program is 15925. When your program started at main, that new process was given a PID of 22731. Then, when your process (22731) did fork(), the child process was given a PID of 22732.

    What this ultimately means is that a call to getpid() in user2 gets you 22731, for two reasons: