C alternative to signal () + alarm ()
I am building some FastCGI applications and it seems to me that lighttpd does not kill them after they are idle, so I am trying to close them myself.
I tried to use
signal(SIGALRM, close);
alarm(300);
and the close function does exit (0) and it works almost well.
The problem is that the close function is called every time the main program loop is executed (I call alarm (300) every loop to reset it). I read the man page for alarm () and it looks like calling it multiple times with the same value should disable SIGALRM, so I'm assuming Lighttpd is sending the alarm.
Great question! Is there a way to run the method after a certain interval, and so that this interval can be reset without SIGALRM? It would be nice if I had multiple alarms.
Here's the whole app:
#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);
}
source to share
Here's a solution that avoids the question, but it works. It will only respond to events in my application:
void close(int intSignal, siginfo_t *info, void *context)
{
// For some stupid reason MY signal doesn't populate siginfo_t
if (!info)
{
count++;
}
}
If the siginfo structure is empty, it is because alarm () triggered. If the external process does this, siginfo_t.si_pid is filled with zero.
I still don't like this solution, but it works. The odd problem is that executing exit (0) does not close the application, even though lighttpd thinks it is gone and spawns another. This means that I now have rosy processes. raise(SIGUSR1)
which should stop FastCGI scripts doesn't seem to do the trick ... hmmm ...
The question still remains: how do you call asynchronous functions on an interval timer without using signals?
source to share
I would use POSIX timers. Timers should not use signals. You have a choice between not notifying at all, raising a signal, or starting the function as a new thread (which I would do since it won't interfere with fastcgi).
Make sure you include <signal.h>
and <time.h>
and link with-lrt
First, I filled in your sigevent structure:
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
};
Now create your timer:
timer_t myTimer;
if(timer_create(CLOCK_REALTIME, &myTimerSignal, &myTimer)){
//An error occurred, handle it
}
Let's take it, it will call the close () function on a new thread in 300 seconds:
struct itimerspec timeUntilClose = {
.it_value = {
.tv_sec = 300 //300 seconds
}
};
if(timer_settime(myTimer, 0, &timeUntilClose, NULL)){
//Handle the error
}
You should now have a timer ready to stop the program after 300 seconds. I know I might be late, but I hope this helps a future reader.
source to share