Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel an alarm() signal via a child process?

For an assignment, I am working on creating a time aware shell. The shell forks and executes commands and kills them if they run for more than a set amount of time. For example.

 input# /bin/ls
 a.out code.c
 input# /bin/cat
 Error - Expired After 10 Seconds.
 input#

Now, my question is: is there a way to prevent the alarm from starting if an error is incurred in the processing of the program, that is, when exevce returns -1?

Since the child-process runs separately and after hours of experimenting and research I have yet to find anything that discusses or even hints at this type of task, I have a feeling it may be impossible. If it is indeed impossible, how can I prevent something like the following from happening...

 input# /bin/fgdsfgs
 Error executing program
 input# Error - Expired After 10 Seconds.

For context, here is the code I am currently working with, with my attempt at doing this myself removed. Thanks for the help in advance!

while(1){
    write(1, prompt, sizeof(prompt)); //Prompt user
    byteCount = read(0, cmd, 1024); //Retrieve command from user, and count bytes
    cmd[byteCount-1] = '\0';    //Prepare command for execution

    //Create Thread
    child = fork();

    if(child == -1){
        write(2, error_fork, sizeof(error_fork));
    }

    if(child == 0){ //Working in child
        if(-1 == execve(cmd,arg,env)){  //Execute program or error
            write(2, error_exe, sizeof(error_exe));
        }   
    }else if(child != 0){   //Working in the parent
        signal(SIGALRM, handler);   //Handle the alarm when it goes off
        alarm(time);
        wait();
        alarm(0);
    }
}
like image 706
Suki Avatar asked Feb 21 '23 18:02

Suki


1 Answers

According to the man page:

Description

The alarm() function shall cause the system to generate a SIGALRM signal for the process after the number of realtime seconds specified by seconds have elapsed. Processor scheduling delays may prevent the process from handling the signal as soon as it is generated.

If seconds is 0, a pending alarm request, if any, is canceled.

Alarm requests are not stacked; only one SIGALRM generation can be scheduled in this manner. If the SIGALRM signal has not yet been generated, the call shall result in rescheduling the time at which the SIGALRM signal is generated.

Interactions between alarm() and any of setitimer(), ualarm(), or usleep() are unspecified.

So, to cancel an alarm: alarm(0). It is even present in your sample code.

The main problem

By the way, you're missing an important piece here:

if(child == 0){ //Working in child
    if(-1 == execve(cmd,arg,env)){  //Execute program or error
        write(2, error_exe, sizeof(error_exe));
        _exit(EXIT_FAILURE);  // EXIT OR A FORKED SHELL WILL KEEP GOING
    }   
}else if(child != 0){   //Working in the parent
like image 160
C2H5OH Avatar answered Feb 27 '23 00:02

C2H5OH