0

我有这个代码(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 停止响应请求。server.pl 的 strace 显示:

futex(0x7f5035818e80, FUTEX_WAIT_PRIVATE, 2, NULL

为什么会这样?

4

1 回答 1

0

我有完全相同的问题,但有其他信号。原因在于您使用 SA_RESTART POSIX 信号处理程序,甚至与 perl 无关。这完全取决于您在警报子中使用的呼叫。在我的情况下,它是 localtime()(但通过 Sys::Syslog)不在安全列表中,因此需要设置快速用户锁定(futex)。

你可以在这里阅读

我还没有找到一个好的解决方案。常规的 perl 信号处理是可以的,但是如果没有 SA_RESTART,许多像 oracle DB 库这样执行 I/O 的库将“随机”退出它们的调用。

如果您可以不使用 SA_RESTART 和 POSIX 处理程序,只需使用 %SIG - 这在 FCGI 中甚至是不可能的。

于 2014-10-24T09:31:37.747 回答