2
votes

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);
} 
1
fork() returns the child PID. Put it in a global variable and use that in the signal handler. - Barmar
BTW, your line "Parent: My child has been spawned" is printed by the child, not the parent as it claims. - Barmar

1 Answers

4
votes

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