我正在编写一个 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/