3

私はいくつかの FastCGI アプリを構築していますが、アイドル状態になった後に lighttpd がそれらを強制終了しないというバグがあるので、それらを自分で閉じようとしています。

使ってみた

signal(SIGALRM, close);
alarm(300);

close 関数に exit(0) を実行させると、ほぼうまく機能します。

問題は、メイン プログラムのループが実行されるたびに close 関数が呼び出されることです (ループをリセットするたびに alarm(300) を呼び出します)。alarm() のマニュアル ページを読みましたが、同じ値で複数回呼び出すと SIGALRM が作動するようには見えないので、Lighttpd がアラーム信号を送信していると想定しています。

大きな質問です!特定の間隔の後にメソッドを実行し、その間隔を SIGALRM なしでリセット可能にする方法はありますか? 目覚ましも複数あればいいのに。

これまでのアプリ全体は次のとおりです。

#include <stdlib.h>
#include <stdarg.h>
#include <signal.h>
#include "fcgiapp.h"

FCGX_Stream     *in, *out, *err;
FCGX_ParamArray envp;
int calls = 0;

void print(char*, ...);
void close();

int main(void)
{
        // If I'm not used for five minutes, leave
        signal(SIGALRM, close);

        int reqCount = 0;

        while (FCGX_Accept(&in, &out, &err, &envp) >= 0)
        {
                print("Content-type: text/plain\r\n\r\n");

                int i = 0;
                char **elements = envp;
                print("Environment:\n");
                while (elements[i])
                        print("\t%s\n", elements[i++]);

                print("\n\nDone. Have served %d requests", ++reqCount);
                print("\nFor some reason, close was called %d times", calls);

                alarm(300);
        }

        return 0;
}

void print(char *strFormat, ...)
{
        va_list args;
        va_start(args, strFormat);
        FCGX_VFPrintF(out, strFormat, args);
        va_end(args);
}

void close()
{
        calls++;
//      exit(0);
}
4

6 に答える 6

2

最善の方法は、シグナルとアラームを削除できるようにスレッドを追加し、スレッドとメインコード(メインスレッド)を同期することです。

于 2009-10-12T12:52:24.903 に答える
0

alarm呼び出しの引数は、分ではなくです。つまり、メインループを通過するたびに5秒以内にウェイクアップするように求めています。

于 2009-10-11T21:40:02.213 に答える
0
  • すべてのファイル記述子(stdinとstdoutを含む)を閉じてみてください。これにより、CGIインスタンスがアイドル状態の場合に閉じる必要があります。
  • select()SIGALRMの代わりに、タイムアウトを使用してスケジュールを設定できます
于 2009-10-11T21:58:00.163 に答える
0

これは、質問の要点を回避するソリューションですが、機能します。アプリケーションのシグナルイベントにのみ応答します。

void close(int intSignal, siginfo_t *info, void *context)
{
        // For some stupid reason MY signal doesn't populate siginfo_t
        if (!info)
        {
                count++;
        }
}

siginfo構造体が空の場合、alarm()がそれをトリップしたためです。外部プロセスがそれを行う場合、siginfo_t.si_pidにはゼロが入力されます。

私はまだこの解決策が好きではありませんが、それは機能します。奇妙な問題は、exit(0)を実行してもアプリケーションが閉じないことですが、lighttpdはそれがなくなったと見なし、別のアプリケーションを生成します。これは、今私がルージュなプロセスを持っていることを意味します。raise(SIGUSR1)これはFastCGIスクリプトを停止することになっているものでも、うまくいかないようです...うーん...

疑問はまだ残っています:信号を使用せずにインターバルタイマーで非同期関数を呼び出すにはどうすればよいですか?

于 2009-10-11T23:01:23.083 に答える
0

おそらく、最初に sleep() を呼び出す別の関数で close 関数をラップできますか?

于 2009-10-11T21:07:54.720 に答える