I'm building some FastCGI apps and it sort of bugs me that lighttpd doesn't kill them off after they've been idle, so I'm trying to have them close on their own.
I tried using
signal(SIGALRM, close);
alarm(300);
and having the close function execute exit(0), and that works almost well.
The problem is the close function is being called every time the main program loop runs though (I call alarm(300) each loop to reset it). I've read the man page for alarm() and it doesn't seem as though calling it multiple times with the same value should trip SIGALRM so I'm assuming Lighttpd is sending an alarm signal.
The big question! Is there a way to run a method after a specific interval, and have that interval be resettable without SIGALRM? I'd be nice if I could have multiple alarms as well.
Here's the whole app thus far:
#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);
}
the best way is: add a thread so that you can remove signal and alarm, and sync the thread and your main code (main thread).
I'd probably use POSIX timers. Timers do not have to use signals. You have a choice between not notifying at all, raising a signal, or running a function as a new thread (which I would do as it will not interfere with fastcgi).
Make sure you include <signal.h> and <time.h>, and link with -lrt
First, I'd fill out 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
}
Lets arm it, it will call close() in 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
}
Now, you should have a timer ready to stop the program after 300 seconds. I know I may be late, but I hope this helps a future reader.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With