我有这个代码(server.pl):
#!/usr/bin/perl
use strict;
use warnings;
use FCGI;
use POSIX qw(:signal_h);
use Time::HiRes qw(alarm);
my $socket = FCGI::OpenSocket(":9010", 10000);
my $request = FCGI::Request(\*STDIN, \*STDOUT, \*STDERR, \%ENV, $socket, FCGI::FAIL_ACCEPT_ON_INTR);
my $old_sigaction = POSIX::SigAction->new;
my $sigaction = POSIX::SigAction->new('sig_alarm', undef, POSIX::SA_RESTART);
POSIX::sigaction(SIGALRM, $sigaction, $old_sigaction) or die "can't sigaction: $!";
sub sig_alarm {
print "alarm " . rand() . "\n";
alarm(0.01);
}
alarm(0.01);
while($request->Accept() >= 0) {
print "Content-type: text/plain\n\n1\n";
}
这是一个FCGI服务器。它侦听端口9010.它有一个线程。服务器每10毫秒在屏幕上打印一个随机文本。
Nginx将请求传递给此服务器。
nginx配置的一部分:
location /counter/ {
fastcgi_pass 127.0.0.1:9010;
include fastcgi_params;
}
我启动server.pl:
$ ~/server.pl
alarm 0.309887429307313
alarm 0.0700285703382804
alarm 0.524615473850769
alarm 0.518569373615669
...
Server.pl正在屏幕上打印文本。
然后我启动这个命令:
/usr/local/apache/bin/ab -k -c 80 -t 300 http://127.0.0.1/counter/
有时server.pl会停止响应请求。 strace for server.pl显示:
futex(0x7f5035818e80, FUTEX_WAIT_PRIVATE, 2, NULL
为什么会这样?
答案 0 :(得分:0)
我有完全相同的问题,但有其他信号。原因在于您使用SA_RESTART POSIX信号处理程序,甚至与perl无关。这完全取决于您在警报子中使用的呼叫。在我的情况下,它的localtime()(但通过Sys :: Syslog)不在安全列表中,因此需要设置快速用户锁(futex)。
您可以阅读here
我还没有找到一个好的解决方案。定期的perl信号处理是可以的,但是没有SA_RESTART,很多像Iracle DB库那样执行I / O的库将会随机退出#34;#34;。
如果没有SA_RESTART和POSIX处理程序,只需使用%SIG - 在FCGI中甚至可能无法实现。