2

Thread::Pool::Simple用来创建一些工作线程。每个工作线程都会做一些事情,包括调用 ,chdir然后执行外部 Perl 脚本(从jbrowse基因组浏览器,如果重要的话)。我capturex用来调用外部脚本并死于其失败。

我发现当我使用多个线程时,事情开始变得一团糟。经过一番研究。似乎某些线程的当前目录不正确。

也许chdir在线程之间传播(即不是线程安全的)?或者也许它是什么capturex

那么,如何安全地为每个线程设置工作目录呢?

** 更新 **

按照执行时更改目录的建议,我想问一下我应该如何将这两个命令传递给capturex

目前我有:

my @args = ( "bin/flatfile-to-json.pl", "--gff=$gff_file", "--tracklabel=$track_label", "--key=$key", @optional_args );
capturex( [0], @args );

如何添加另一个命令@args?是否会capturex因任何命令的错误而继续死亡?

4

2 回答 2

2

我不认为“当前工作目录”是每个线程的属性。我希望它是该过程的一个属性。

不过,目前还不清楚为什么你需要使用chdir它。您不能启动外部脚本来适当地设置进程的工作目录吗?这听起来像是一种更可行的方法。

于 2010-09-19T08:46:38.200 回答
2

我认为您可以通过放弃IPC::System::Simple不适合该工作的工具来很容易地解决您的“在运行命令之前我如何在孩子中进行 chdir”问题。

而不是做

my $output = capturex($cmd, @args);

做类似的事情:

use autodie qw(open close);
my $pid = open my $fh, '-|';
unless ($pid) { # this is the child
  chdir($wherever);
  exec($cmd, @args) or exit 255;
}
my $output = do { local $/; <$fh> };
# If child exited with error or couldn't be run, the exception will
# be raised here (via autodie; feel free to replace it with 
# your own handling)
close ($fh);

如果您从 获取行列表而不是标量输出capturex,则唯一需要更改的是倒数第二行 (to my @output = <$fh>;)。

更多关于 forking-open 的信息在perldoc perlipc中。

这样做的好处capture("chdir wherever ; $cmd @args")是它不会让 shell 有机会对你的@args.

更新的代码(不捕获输出)

my $pid = fork;
die "Couldn't fork: $!" unless defined $pid;
unless ($pid) { # this is the child
  chdir($wherever);
  open STDOUT, ">/dev/null"; # optional: silence subprocess output
  open STDERR, ">/dev/null"; # even more optional
  exec($cmd, @args) or exit 255;
}
wait;
die "Child error $?" if $?;
于 2010-09-19T11:17:55.647 回答