2009-11-17 266 views
1

我有一个Perl脚本,它执行fork/exec来在后台启动另一个工具并监视某些文件系统更改这个其他工具正在运行。这似乎像预期的那样工作。Perl Script,Fork/Exec,System声明我的进程已经死亡,但实际上只有我的子进程已经死亡

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

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

我不明白是什么让bash相信我的流程已经退出。我尝试在脚本中阻止SIGCHLD信号,我尝试关闭和/或重定向STDOUT/STDERR/STDIN(它们在叉上复制,但你永远不知道) - 没有成功。我甚至尝试着名的“双叉”,使最终的孩子独立于我的脚本过程,获得相同的结果。无论我做什么,只要我的孩子(或孙子)死亡,Bash就会认为我的过程已经退出。在后台启动我的脚本(在末尾使用“&”)使得Bash甚至告诉我XYZ过程已经完成(并且它在这里命名我的过程,而不是子进程,尽管我的进程很快活着并且通过终端打印STDOUT那一刻)。

如果这只是Bash的一个问题,我不会在意,但其他第三方应该运行我的脚本的软件的行为方式也是一样的。一旦我的孩子死亡,他们声称我的剧本事实上已经死亡,这根本不是事实。

+2

我认为,而不是这个散文描述,它会更有帮助的,而不是你的代码减少到最小的可能的大小,说明你的问题,并张贴。如果在这个过程中你的问题消失了,你已经获得了有用的调试信息。 – 2009-11-17 19:04:44

+0

同意亚当。让我看看代码! (对Jerry Maguire道歉) – 2009-11-17 19:08:41

+0

对不起,没有发布任何代码,在尝试找到这个问题的原因约30分钟后,我还剩下10分钟才离开(否则我会错过一次重要的约会) - 上面的描述是我能在10分钟内得出的最好的结果(将代码剥离到最小的测试用例需要更多的时间)。我从现在开始的11个小时内再次访问代码;那么我会看看我能做些什么关于代码示例。 – Mecki 2009-11-17 22:08:56

回答

1

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

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

man fork

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

+0

嗯......好点你在那里...我会仔细检查,在从现在开始的11个小时内(这是当我将再次访问我的代码)。这确实是一个愚蠢的错误,但每个人偶尔会犯一些愚蠢的错误,如果它是在错误的分支中执行exec,这确实会符合上述不希望的行为。 – Mecki 2009-11-17 22:04:32

+0

你是对的 - 在exec显示exec运行在父进程而不是在子进程之前打印一些调试输出 - DOOHH!愚蠢的错误! – Mecki 2009-11-18 09:16:03