如何通过子进程取消alarm()信号?

时间:2012-04-19 23:45:09

标签: c signals alarm child-process

对于作业,我正在创建一个时间感知的shell。如果shell运行超过一定的时间,它会分叉并执行命令并将其杀死。例如。

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

现在,我的问题是:如果在程序处理过程中出现错误,也就是说,当exevce返回-1时,有没有办法阻止警报启动?

由于儿童过程分开进行,经过数小时的实验和研究后,我还没有找到任何讨论甚至暗示这类任务的内容,我觉得这可能是不可能的。如果确实不可能,我怎么能防止发生以下事情......

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

对于上下文,这是我目前正在使用的代码,我自己尝试删除这些代码。感谢您的帮助!

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);
    }
}

2 个答案:

答案 0 :(得分:6)

根据man page

  

<强>描述

     

alarm()函数将使系统在经过秒指定的实时秒数后,为进程生成SIGALRM信号。处理器调度延迟可能会阻止进程在生成信号后立即处理信号。

     

如果秒为0,则取消挂起的警报请求(如果有)。

     

警报请求未堆叠;只能以这种方式安排一个SIGALRM生成。如果尚未生成SIGALRM信号,则呼叫将导致重新安排SIGALRM信号生成的时间。

     

未指定alarm()与任何setitimer(),ualarm()或usleep()之间的交互。

所以,要取消闹钟:alarm(0)。它甚至出现在您的示例代码中。

主要问题

顺便说一句,你在这里错过了一个重要的部分:

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

答案 1 :(得分:1)

wait()系统调用需要参数;为什么不编译源文件中的正确头文件以及未声明函数的编译器警告(最好是错误)?或者,如果您收到此类警告,请在提交代码以便审核StackOverflow等地点之前注意这些警告。

您无需从execve()(或任何exec*()函数)测试返回状态;如果它返回,则失败。

最好在失败时写错误。如果子进程也退出会更好,这样它就不会回到while (1)循环,与主shell竞争输入数据。

if (child == 0)
{
    execve(cmd, arg, env);
    write(2, error_exe, sizeof(error_exe));
    exit((errno == ENOEXEC) ? 126 : 127);
}

事实上,您孩子的退出是导致问题的主要原因;由于孩子没有退出,闹钟响起之前等待不会返回。显示的退出状态旨在匹配POSIX shell规范。