【发布时间】:2015-04-28 12:19:58
【问题描述】:
我遇到了只偶尔出现的 fork 问题。它基本上一直有效,但在测试系统上每隔一段时间就会失败。
我的研究没有发现其他人提到类似的问题。
问题出现在嵌入式 Linux 系统上。没有可用的交换分区。
正在运行的进程在所有线程中阻塞了所有信号,并在专用线程中通过 sigtimedwait 处理它们。
如果我通过 fork 启动子进程:
- 父进程继续返回值 > 0。因此,fork 工作。返回 no -1 - 所以没有错误,没有内存不足!然后父进程等待子进程并且永远不会从等待中返回。
- 子进程从不做任何事情可观察。子进程应该做的第一件事就是写一条日志消息。此日志消息永远不会出现。然后它应该产生两个孩子 处理一个超时进程和一个工作进程。这些进程永远不会出现。
- 如果我在命令行上通过 ps 检查,我可以看到现有的子进程。它处于状态 S(可中断睡眠(等待事件完成))。它永远不会获得任何 CPU 时间,它不会显示任何 CPU 使用率。
- 如果我kill -9子进程,父进程完成等待并愉快地继续。
显示问题的伪代码:
const pid_t childPid = fork();
if(0 == childPid) {
// child process
LOG_MSG("Child process started."); // <- This never shows up in the syslog.
// do some stuff
} else if(-1 == childPid) {
// error
LOG_MSG("Parent process: Error starting child process!");
result = false;
} else {
// parent process
LOG_MSG("Parent process: Child process started. PID: %.", childPid); // <- This shows up in the syslog.
// do some stuff
int status = 0;
const int options = 0;
const auto waitResult = waitpid(childPid, &status, options);
// more stuff
}
问题:
- 什么可能导致这个挂起的子进程?
- 如果新进程在导致 syslog 的 LOG_MSG 调用中内存不足,会发生什么情况?这会引发一个信号(因为它被阻止而无法传递)?
【问题讨论】:
-
LOG_MSG的定义是什么? -
你能用“strace”运行你的程序,使用“-ff”选项来跟随分叉吗?例如“strace -o output.txt -ff your_program”。您应该看到父进程及其产生的任何子进程的跟踪文件。这些文件中的信息可能很有启发性。
-
我认为
LOG_MSG是这里的关键。如果父母和孩子都在争夺LOG_MSGs 资源,我不会感到惊讶,这就是问题所在。 -
您说它处于可中断睡眠状态,等待事件完成。看起来它正在等待一个锁(到日志文件)并且父级持有该锁。