waitpid blocking when it shouldn't

Fingolfin :

I am writing a mini-shell(no, not for school :P; for my own enjoyment) and most of the basic functionality is now done but I am stuck when trying to handle SIGTSTP.

Supposedly, when a user presses Ctrl+Z, SIGTSTP should be sent to the Foreground process of the shell if it exists, and Shell should continue normally.

After creating each process(if it's a Foreground process), the following code waits:

if(waitpid(pid, &processReturnStatus, WUNTRACED)>0){//wait stopped too
    if(WIFEXITED(processReturnStatus) || WIFSIGNALED(processReturnStatus))
        removeFromJobList(pid);
}

And I am handling the signal as follows:

void sigtstpHandler(int signum)
{
    signum++;//Just to remove gcc's warning
    pid_t pid = findForegroundProcessID();
    if(pid > -1){
        kill(-pid, SIGTSTP);//Sending to the whole group
    }
}

What happens is that when I press Ctrl+Z, the child process does get suspended indeed(using ps -all to view the state of the processes) but my shell hangs at waitpid it never returns even though I passed WUNTRACED flag which as far as I understood is supposed to make waitpid return when the process is stopped too.
So what could I have possible done wrong? or did I understand waitpid's behavior incorrectly?

Notes:
-findForegroundProcessID() returns the right pid; I double checked that.
-I am changing each process's group when right after I fork
-Handling Ctrl+C is working just fine
-If I use another terminal to send SIGCONT after my shell hangs, the child process resumes its work and the shell reaps it eventually.
-I am catching SIGTSTP which as far as I read(and tested) can be caught. -I tried using waitid instead of waitpid just in case, problem persisted. EDIT:

void sigchldHandler(int signum)
{
    signum++;//Just to remove the warning
    pid_t pid;
    while((pid = waitpid(-1, &processReturnStatus, 0)) > 0){    
        removeFromJobList(pid);
    }
    if(errno != ECHILD)
        unixError("kill error");
}

My SIGCHLD handler.

fizzer :

SIGCHLD is delivered for stopped children. The waitpid() call in the signal handler - which doesn't specify WUNTRACED - blocks forever.

You should probably not have the removeFromJobList() processing in two different places. If I had to guess, it sounds like it touches global data structures, and doesn't belong in a signal handler.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related