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 をリッスンします。1 つのスレッドがあります。サーバーは、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 に答える