Question

I'm trying to do an assignment for one of my classes and no professors/fellow classmates are getting back to me. So before you answer, please don't give me any exact answers! Only explanations!

What I have to do is write a c program (timeout.c) that takes in two command line arguments, W and T, where W is the amount of time in seconds the child process should take before exiting, and T is the amount of time the parent process should wait for the child process, before killing the child process and printing out a "Time Out" message. Basically, if W > T, there should be a timeout. Otherwise, the child should finish its work and then no timeout message is printed.

What I wanted to do was just have the parent process sleep for T seconds, and then kill the child process and print out the timeout, however printing out the timeout message would happen no in both cases. How do I check to see that the child process is terminated? I was told to use alarm() for this, however I have no idea of what use that function would serve.

Here's my code in case anyone wants to take a look:

void handler (int sig) {
    return;
}

int main(int argc, char* argv[]){
    if (argc != 3) {
    printf ("Please enter values W and T, where W\n");
    printf ("is the number of seconds the child\n");
    printf ("should do work for, and T is the number\n");
    printf ("of seconds the parent process should wait.\n");
    printf ("-------------------------------------------\n");
    printf ("./executable <W> <T>\n");
    }

    pid_t pid;
    unsigned int work_seconds = (unsigned int) atoi(argv[1]);
    unsigned int wait_seconds = (unsigned int) atoi(argv[2]);

    if ((pid = fork()) == 0) {
        /* child code */
        sleep(work_seconds);
        printf("Child done.\n");
        exit(0);
    }

    sleep(wait_seconds);
    kill(pid, SIGKILL);
    printf("Time out.");

    exit(0);
}
Was it helpful?

Solution

Although waitpid would get you the return status of the child, its default usage would force parent to wait until the child terminates.

But your requirement (if i understood correctly) only wants parent to wait for a certain time, alarm() can be used to do that.

Then, you should use waitpid() with a specific option that returns immediately if the child has not exited yet (study the api's parameters). So if the child didn't exit, you could kill it, else you already receive its return status.

OTHER TIPS

You want the timeout program to stop more or less as soon as the command finishes, so if you say timeout -t 1000 sleep 1 the protecting program stops after about 1 second, not after 1000 seconds.

The way to do that is to set an alarm of some sort — classically, with the alarm() system call and a signal handler for SIGALRM — and then have the main process execute wait() or waitpid() so that when the child dies, it wakes up and collects the corpse. If the parent process gets the alarm signal, it can print its message and send death threats of some sort to its child. It might be sensible to try SIGTERM and/or SIGHUP before resorting to SIGKILL; the SIGTERM and SIGHUP signals give the errant child a chance to clean up whereas SIGKILL does not.

If you know how to manage signals, you could catch SIGALRM and SIGCHLD in your parent process. SIGCHLD will be raised when the client terminates, and SIGALRM when the timer expires. If the first raised signal is SIGALRM, the timeout expired, otherwise, if the first SIGNAL that the parent catches is SIGCHLD, the child has stopped before the expiration of the timeout.

wait() or waitpid() would still be necessary to collect the terminated child.

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