我正在构建一些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);
}
答案 0 :(得分:2)
最好的方法是:添加一个线程,以便您可以删除信号和警报,并同步线程和主代码(主线程)。
答案 1 :(得分:1)
我可能会使用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
}
让它武装它,它将在300秒内在新线程中调用close():
struct itimerspec timeUntilClose = {
.it_value = {
.tv_sec = 300 //300 seconds
}
};
if(timer_settime(myTimer, 0, &timeUntilClose, NULL)){
//Handle the error
}
现在,你应该有一个计时器准备好在300秒后停止程序。我知道我可能会迟到,但我希望这有助于未来的读者。
答案 2 :(得分:0)
也许你可以通过另一个首先调用sleep()的函数来包装close函数?
答案 3 :(得分:0)
alarm
来电的参数是秒,而不是分钟。所以你要求每次通过主回路后在5秒内醒来。
答案 4 :(得分:0)
select()
超时来安排而不是SIGALRM 答案 5 :(得分: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将填充为零。
我仍然不喜欢这个解决方案,但它确实有效。奇怪的问题是,退出(0)不会关闭应用程序,尽管lighttpd认为它已经消失并产生另一个应用程序。这意味着现在我有了胭脂流程。 raise(SIGUSR1)
这应该是什么阻止FastCGI脚本似乎没有做到这一点...嗯......
问题仍然存在:如何在不使用信号的情况下在间隔定时器上调用异步函数?