3

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?

1 Answers1

1

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);
    }
}
Jean-Baptiste Yunès
  • 34,548
  • 4
  • 48
  • 69
  • thank you this code does what I want to do. Just a little problem, when I send the sigcont the handler print in handler, but parent doesn't print continued =1. (with stop function it works) –  Dec 07 '14 at 11:50
  • I'm using linux 3.17.4-1 (with chakra linux os) –  Dec 07 '14 at 11:59
  • 1
    `printf()` isn't async-signal-safe and shouldn't be called in a signal handler. See [here](https://www.securecoding.cert.org/confluence/display/seccode/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers), [here](http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html), and [here](https://docs.oracle.com/cd/E19455-01/806-5257/gen-26/index.html) – Kenster Dec 07 '14 at 12:15
  • I forgot the `WCONTINUED` flag to the call : `waitpid(-1,&x,WUNTRACED|WCONTINUED)` – Jean-Baptiste Yunès Dec 07 '14 at 12:45