Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

c alternative to signal() + alarm()

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);
}

2 Answers

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).

like image 68
Test Avatar answered Mar 27 '26 12:03

Test


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.

like image 44
user233009 Avatar answered Mar 27 '26 11:03

user233009



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!