Search code examples
csigchld

How to handle SIGHLD


I'm having some troubles using sigchld...

what I want to do is to create a child process with fork and make the child print and sleep a second for a couple of times... during these process I want to send signal to child (SIGSTOP and SIGCONTINUED) and I want the parent to print what the signal was... here's my code:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
void handler (int i) {
    int x;
    waitpid(-1,&x, 0);
    printf("WIFSTOPPED=%d, WIFCONTINUED=%d\n", WIFSTOPPED(x),WIFCONTINUED(x) );
}

int main(){

    int x;
    int q=fork();
    if(q==0){
        int i=0;
        printf("%d\n",getpid());
        while (i<20){
            printf("%d\n", i++);
            sleep(1);
        }
        _exit(0);
    }
    else {
        signal(SIGCHLD, handler);
        waitpid(-1,&x, 0);
        while(WIFEXITED(x)!=1){
            waitpid(-1,&x, 0);
            sleep(1);
        }
        exit(0);
    }
}

but it doesn't work beacause when I send a SIGSTOP or SIGCONTINUED to the child, the child stop and continue but the parent doesn't print anything

any suggestion?


Solution

  • Your handler shall not call waitpid again and you main while loop is also not correct : again you call waitpid twice the first time. And last, your waitpid call much declare to be interested in status changes (WUNTRACED option).

    A much correct code could be :

    void handler (int i) { // a handler just handle the fact some signal occured
        printf("in handler\n");
    }
    
    int main(){
        int x;
        int q=fork();
        if(q==0){
            int i=0;
            printf("%d\n",getpid());
            while (i<20){
                printf("%d\n", i++);
                sleep(1);
            }
            _exit(0);
        }
        else {
            signal(SIGCHLD, handler); // catch child status changes
            do {
                waitpid(-1,&x, WUNTRACED|WCONTINUED); // wait until child terminates or changes its status
                if (WIFSTOPPED(x)|WIFCONTINUED(x)) // test what really happens
                    printf("STOPPED=%d, CONTINUED=%d\n", WIFSTOPPED(x),WIFCONTINUED(x) );
            } while(!WIFEXITED(x));
            exit(0);
        }
    }