【问题标题】:Perl Script, Fork/Exec, System claims my process has died when in fact only my child process has diedPerl 脚本,Fork/Exec,系统声称我的进程已经死了,而实际上只有我的子进程已经死了
【发布时间】:2010-12-17 14:01:22
【问题描述】:

我有一个 Perl 脚本,它执行 fork/exec 以在后台启动另一个工具并在另一个工具运行时监视一些文件系统更改。这似乎按预期工作。

当我从 shell(例如 Bash)启动这个 Perl 脚本时,当然只要我的 Perl 脚本正在运行,shell 提示就应该消失。它将继续运行,直到发生预期的文件修改;但不能保证文件修改可能由外部工具完成,在这种情况下,外部工具将退出,但我的脚本将继续运行并且必须以某种方式处理这种情况 - 这种处理超出了问题的范围和与我的问题无关(到目前为止它甚至还没有实现)。

我的问题是,一旦我的子进程死亡,Bash 就会返回提示符,声称我的进程已完成运行......这是不正确的。它显然仍在后台运行,并且仍在等待文件系统修改。如果我在脚本的主循环中继续打印一些文本,即使 bash 已经返回到提示符,仍然会打印这些文本。

我无法弄清楚是什么让 bash 相信我的进程已经退出。我尝试在我的脚本中阻止 SIGCHLD 信号,我尝试关闭和/或重定向 STDOUT/STDERR/STDIN(在 fork 上重复,但你永远不知道) - 没有成功。我什至尝试了著名的“双叉”,使最终的孩子独立于我的脚本过程,同样的结果。无论我做什么,只要我的孩子(或孙子)死了,Bash 相信我的过程已经结束。在后台启动我的脚本(在最后使用“&”)使 Bash 甚至告诉我进程 XYZ 已经完成(并且它在这里命名我的进程,而不是子进程,即使我的进程很高兴地活着并通过打印到终端就在那一刻标准输出)。

如果这只是 Bash 的一个问题,我不在乎,但是应该运行我的脚本的其他第三方软件的行为方式相同。我的孩子一死,他们就声称我的剧本实际上已经死了,这根本不是真的。

【问题讨论】:

  • 我认为,与这种散文描述相比,将代码缩减到能说明您的问题的最小可能大小并将其发布对您更有帮助。如果在执行此操作的过程中您的问题消失了,那么您就获得了有用的调试信息。
  • 同意亚当。给我看代码! (向杰里·马奎尔道歉。)
  • 很抱歉没有发布任何代码,在试图找到这个问题的原因大约 30 分钟后,我离离开的时间正好还剩 10 分钟(否则我会错过一个重要的约会) - 上面的描述是我能在 10 分钟内得出的最好的描述(将代码剥离到最小的测试用例需要更多时间)。从现在起正好 11 小时后,我可以再次访问代码;然后我会看看我能对代码示例做些什么。

标签: perl macos scripting fork


【解决方案1】:

只是一个健全的检查,你的主程序走对了吗?它应该遵循非零路径:

my $pid = fork;
if ($pid == 0) {
    print "Child\n";
} else {
    print "Main\n";
}

来自man fork

成功完成后,fork() 向孩子返回值 0 进程并返回进程ID 子进程到父进程 过程。

【讨论】:

  • Ummm... 好点子...我会在 11 小时后再次检查(此时我可以再次访问我的代码)。这确实是一个愚蠢的错误,但每个人都会偶尔犯愚蠢的错误,如果它在错误的 fork 中执行 exec,这确实会符合上述不良行为。
  • 你是对的 - 在 exec 之前打印一些调试输出显示 exec 在父级而不是子级中运行 - DOOHH!愚蠢的错误!!!
猜你喜欢
  • 1970-01-01
  • 2013-07-04
  • 1970-01-01
  • 1970-01-01
  • 2014-03-29
  • 2018-09-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多