Linux – Killing a child process from a signal handler

clinuxshellunix

I'm writing a simple shell, and I have to fork a child process an external program using execv. I have to send the signal TSTP(Cntl+Z) to the signal handler, and then kill the currently running child process. My problem is I can't find a way to pass the Child pid into the signal handler. If i do a getpid() in the handler, it just returns the parent pid. I also tried setting the child pid as getpid() inside the child process, and having that variable as a global variable, but that also didn't work. Here is some of the code I have so far.

void handler(int);
//in main
if (!built_in_cmd(myArgc,myArgs)) {
    pid_t pid;
    char *x = myArgs[0];
    if((pid=fork())<0)
        printf("Parent: fork() process failed");
    else {
        if (pid == 0) {
            y=getpid();
            printf("Parent: My child has been spawned. %d %d\n",y,getppid());
            execv(x, myArgs);
            exit(0);
        }
        else {
            signal(SIGTSTP,handler);
            wait(0);
            printf("Parent: My child has terminated.\n");
        }
    }
}
return;

//outside main
void handler(int signo){
    kill(idk,SIGKILL);
} 

Best Answer

Signals are asynchronous in nature, there's no way to pass any extra state to them except through global variables. Assuming that you only ever have one thread waiting for a child, it's safe to use a global, but otherwise there's no multithread-safe way of doing so:

// At global scope
pid_t child_pid = (pid_t)-1;
...
void myfunc()
{
    pid_t pid;
    if((pid = fork()) < 0)
        ...
    else if(pid == 0)
        ...
    else
    {
        child_pid = pid;
        ...
    }
}