Question

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
Was it helpful?

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.

OTHER TIPS

You see parent process waking up earlier than 20 seconds you've expected is because exiting child has delivered SIGCHLD signal which you've registered to handle. That signal wakes up usleep() prematurely. It returns -1 and has errno set to EINTR.

Check the return value of usleep(). It's certainly EINTR, as defined in the man page: http://linux.die.net/man/3/usleep

You need to add a wait() call in your SIGCHLD handler (http://linux.die.net/man/2/wait).

Note also that it is undefined which process gets run first after the fork(). Even though they are parent and child, they are scheduled independently by the operating system. Also, usleep() guarantees a sleep of no less than the number useconds passed to it, unless interrupted. It does not guarantee that the process will awaken at that time, though normally it will be pretty close.

Don't try to use usleep() or any of its variants for process synchronization. Use the proper IPC routines.

usleep function can not take arguments with values more than 1,000,000 usleep(20000000) should certainly cause an unpredictable behavior.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top