cforkusleep

error in fork and usleep


i write this code: http://ideone.com/cNypUb

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void signchld (int signal){
    fprintf (stderr, "[X] child exited\n");
}


int main(){
    signal (SIGCHLD, signchld);
    int i;
    for(i=0;i<=300;i++){
        pid_t f;
        f=fork();
        if(f==0){
            //child
            usleep(3*1000000);
            fprintf (stderr, "[C1] %d\n",i);
            exit(0);
            fprintf (stderr, "[C2] %d\n",i);
        }else if(f>0){
            fprintf (stderr, "[P1] %d\n",i);
            usleep(20000000);
        fprintf (stderr, "[P2] %d\n",i);
        }
    }
    return 0;
}

but the [p2] run each 3 second and then run next loop

I expect to see this output:

[P1] 0
[C1] 0
[X] child exited

after 20 second

[P2] 0
[P1] 1
[C1] 1
[X] child exited

Solution

  • It is the signal handler signchld() that interrupts usleep() in the parent, as we can prove by substituting

    usleep(20000000);
    

    with

    if (usleep(20000000) < 0) {
        if (errno == EINTR)
            fprintf (stderr, "[PX] usleep() interrupted by a signal\n");
    }
    

    (and of course including errno.h). This will print

    [P1] 0
    [C1] 0
    [X] child exited
    [PX] usleep() interrupted by a signal
    [P2] 0
    [P1] 1
    

    and so on.

    On my system (GNU/Linux) the man page for usleep() reads:

    4.3BSD, POSIX.1-2001. POSIX.1-2001 declares this function obsolete; use nanosleep(2) instead. POSIX.1-2008 removes the specification of usleep().

    Only the EINVAL error return is documented by SUSv2 and POSIX.1-2001.