我使用perl以XML格式返回数据集。现在我遇到了一种情况,我需要在将数据集发送到客户端后运行一些清理工作。但有些地方,在mod perl和Apache的链中,输出会被保留,直到我的方法返回。
我试图用类似的命令清除缓冲区。
$| =1;
STDOUT->flush(); # flush the buffer so the content is sent to the client and the finish hook can carry on, with out delaying the return.
if ($mod_perl_io){
$mod_perl_io->rflush;
}
然而,在我的方法返回之前,我仍然没有输出。然后我发现我的浏览器正在等待连接关闭,发现在标题中设置内容类型应该解决这个问题。
rint $cgi->header(-type => "text/plain; charset=UTF-8", -cookie => $config->{'cookie'});
仍然没有运气,事实上我一直在发送正确的标题。
所以我觉得最好的选择就是简单地启动一个新线程让我的方法返回。但是当我创建一个新线程时。
use threads ('yield',
'stack_size' => 64*4096,
'exit' => 'threads_only',
'stringify');
my $thr = threads->create('doRebuild', $dbconnect, $dbusername, $dbpassword, $bindir);
sub doRebuild {
my ($dbconnect, $dbusername, $dbpassword, $bindir ) = @_;
1;
}
我得到了段错误
[Fri Feb 22 10:16:47 2013] [notice] child pid 26076退出信号分段错误(11)
据我所知,这是由mod perl完成的,以确保线程安全操作。不确定这是否正确。
所以我想我尝试使用{exe}
{exec 'perl', "$bindir/rebuild_needed_values.pl", qw('$dbconnect' '$dbusername' '$dbpassword');}
从我收集的内容来看,这是从mod perl接管的过程,而不是让它返回任何东西。
我知道这不像堆栈溢出的问题那样具体,但是这种事情必须是一个常见的问题,其他人如何解决它?
答案 0 :(得分:1)
您可以使用fork(),但我建议http://gearman.org/进行后台处理。
像Gearman这样的解决方案要好得多,因为你的后台进程不在Apache的流程链中。
如果使用gearman实现,您的进程将在Apache重启后继续存在。它也更安全,因为Gearman环境可以在chroot监狱中运行。
使用Gearman的一个很好的副作用是你的后台进程可以从其他机器甚至其他语言调用。
Gearman还可以在以后轻松收集您的流程中的数据,您可以轻松地将进度信息反馈到您的网络应用。