我正在编写一个 mini-shell(不,不是为了学校:P;为了我自己的乐趣),现在大部分基本功能已经完成,但是在尝试处理 SIGTSTP 时我被卡住了。

假设,当用户按下 Ctrl+Z 时,如果存在 SIGTSTP,则应将 SIGTSTP 发送到 Shell 的 Foreground 进程,Shell 应正常继续。

创建每个进程后(如果是前台进程),下面的代码等待:

if(waitpid(pid, &processReturnStatus, WUNTRACED)>0){//wait stopped too
    if(WIFEXITED(processReturnStatus) || WIFSIGNALED(processReturnStatus))
        removeFromJobList(pid);
}

我正在处理信号如下:
void sigtstpHandler(int signum)
{
    signum++;//Just to remove gcc's warning
    pid_t pid = findForegroundProcessID();
    if(pid > -1){
        kill(-pid, SIGTSTP);//Sending to the whole group
    }
}

发生的情况是,当我按下 Ctrl+Z 时,子进程确实被挂起(使用 ps -all 查看进程的状态)但我的 shell 卡在 waitpid 它永远不会返回,即使我通过了 1321213 的 18413使 WUNTRACED 在进程停止时也返回。
那么我可能做错了什么?还是我错误地理解了waitpid的行为?

笔记:
-findForegroundProcessID() 返回正确的pid;我仔细检查了一下。
- 在我 waitpid 之后,我正在更改每个进程的组
-处理 fork 工作正常
- 如果我在 shell 挂起后使用另一个终端发送 SIGCONT,子进程将恢复其工作,并且 shell 最终会收割它。
-我正在捕获 SIGTSTP,据我阅读(和测试)可以捕获。
- 我尝试使用 waitid 而不是 waitpid 以防万一,问题仍然存在。
编辑:
void sigchldHandler(int signum)
{
    signum++;//Just to remove the warning
    pid_t pid;
    while((pid = waitpid(-1, &processReturnStatus, 0)) > 0){
        removeFromJobList(pid);
    }
    if(errno != ECHILD)
        unixError("kill error");
}

我的 SIGCHLD 处理程序。

最佳答案

SIGCHLD 被传递给停止的 child 。信号处理程序中的 waitpid() 调用 - 未指定 WUNTRACED - 永远阻塞。

您可能不应该在两个不同的地方处理 removeFromJobList()。如果我不得不猜测,听起来它涉及全局数据结构,并且不属于信号处理程序。

关于c - waitpid 在不应该阻塞时阻塞,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14034895/

10-13 07:12