我正在构建一些 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);
}
有帮助吗?

解决方案

最好的办法是:增加一个线程,这样就可以去除信号和报警,并同步线程和主代码(主线程)

其他提示

我可能会使用POSIX计时器。计时器没有使用的信号。你没有通知所有,发出信号,或者运行一个函数作为一个新的线程(我会做,因为它不会FastCGI的干扰)之间进行选择。

请确保您有<signal.h><time.h>,并链接与-lrt

首先,我要填写您的sigevent结构:

struct sigevent myTimerSignal = {
    .sigev_notify = SIGEV_THREAD,
    .sigev_notify_function = close //Make sure you change your function declaration to close(union sigval), you do not need to use the sigval unless you store data in your event too
};

现在创建您的计时器:

timer_t myTimer;
if(timer_create(CLOCK_REALTIME, &myTimerSignal, &myTimer)){
    //An error occurred, handle it
}

允许臂,它会调用close()在一个新的线程在300秒内:

struct itimerspec timeUntilClose = {
    .it_value = {
        .tv_sec = 300 //300 seconds
    }
};

if(timer_settime(myTimer, 0, &timeUntilClose, NULL)){
    //Handle the error
}

现在,你应该准备好后经过300秒来停止程序的计时器。我知道我可能会迟到,但我希望这有助于未来的读者。

也许可以通过另一功能包住关闭功能,这将首先调用睡眠()?

alarm呼叫的参数是,而不是分钟。所以,你问应在5秒内通过主循环以后每次醒来。

下面的排序,避免问题的点解决方案,但它的工作原理。它将只我的应用程序的信号响应事件:

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

如果该SIGINFO结构是空的,这是因为报警()跳闸它。如果外线处理这样做,siginfo_t.si_pid被填入零。

我还是不喜欢这样的解决方案,但它的工作原理。现在奇怪的问题是,做一个出口(0)不关闭应用程序,虽然lighttpd的认为它的消失,并产生另一个。这意味着,现在我已经得到了胭脂的过程。 raise(SIGUSR1)这就是应该停止FastCGI的脚本似乎并没有任何做的伎俩...嗯...

问题仍然存在:如何在一个间隔定时器做一个呼叫异步函数,而无需使用信号

  • 尝试关闭所有文件描述符(包括 stdin 和 stdout)。如果 CGI 实例空闲,这应该会关闭它。
  • 您可以使用 select() 使用超时来安排而不是 SIGALRM
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top