在 child 收到 sigstop 后,wait() 不会 return
wait() does not return after child received sigstop
正如标题所说,一个进程 fork 等待它的 child 收到一个 SIGSTOP(child 自己发送的信号)但是它并没有醒来,就好像它没有收到任何 SIGCHLD(但它确实收到了,用 strace 测试)。
有人有什么想法吗?
int main() {
if (fork()) {
wait(NULL);
write(1, "Bye\n", 4);
} else {
kill(getpid(), SIGSTOP);
write(1, "Hello\n", 6);
}
return 0;
}
它们都挂起,而只有 child 应该挂起。
哎呀,我会自己回答,我忘了添加 WUNTRACED 作为 wait() 选项。
正确的函数调用是 waitpid(-1, NULL, WUNTRACED);
The specification for wait
说它只报告 children 有 exited,而不是 children 有 stopped。你应该使用
waitpid(-1, 0, WUNTRACED);
相反。
标志名称 WUNTRACED
有点神秘 - 为什么不是 WSTOPPED
?这是标准化 wait*
API 与 not-standardized ptrace
API 擦肩而过的一点。比较 POSIX 对 WUNTRACED
的定义…
- WUNTRACED
- The status of any child processes specified by pid that are stopped, and whose status has not yet been reported since they stopped, shall also be reported to the requesting process.
… 及其文档在 Linux manpage …
- WUNTRACED
- also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified.
所以基本上 wait*
的默认行为有一个特殊情况嵌入其中,以方便编写调试器的人(编写调试器的人会利用他们可以获得的一切便利)并且这种特殊情况已经存在了如此之久,以至于它影响了为 waitpid
的旗帜选择的名称。 (我不知道是哪一种方式,但如果得知 ptrace
停止比作业控制停止 更早 ,我不会感到惊讶。)
正如标题所说,一个进程 fork 等待它的 child 收到一个 SIGSTOP(child 自己发送的信号)但是它并没有醒来,就好像它没有收到任何 SIGCHLD(但它确实收到了,用 strace 测试)。
有人有什么想法吗?
int main() {
if (fork()) {
wait(NULL);
write(1, "Bye\n", 4);
} else {
kill(getpid(), SIGSTOP);
write(1, "Hello\n", 6);
}
return 0;
}
它们都挂起,而只有 child 应该挂起。
哎呀,我会自己回答,我忘了添加 WUNTRACED 作为 wait() 选项。 正确的函数调用是 waitpid(-1, NULL, WUNTRACED);
The specification for wait
说它只报告 children 有 exited,而不是 children 有 stopped。你应该使用
waitpid(-1, 0, WUNTRACED);
相反。
标志名称 WUNTRACED
有点神秘 - 为什么不是 WSTOPPED
?这是标准化 wait*
API 与 not-standardized ptrace
API 擦肩而过的一点。比较 POSIX 对 WUNTRACED
的定义…
- WUNTRACED
- The status of any child processes specified by pid that are stopped, and whose status has not yet been reported since they stopped, shall also be reported to the requesting process.
… 及其文档在 Linux manpage …
- WUNTRACED
- also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified.
所以基本上 wait*
的默认行为有一个特殊情况嵌入其中,以方便编写调试器的人(编写调试器的人会利用他们可以获得的一切便利)并且这种特殊情况已经存在了如此之久,以至于它影响了为 waitpid
的旗帜选择的名称。 (我不知道是哪一种方式,但如果得知 ptrace
停止比作业控制停止 更早 ,我不会感到惊讶。)