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

      

+2


source to share


6 answers


the best way is to add a thread so you can remove the alarm and alarm and keep the thread and main code in sync (main thread).



+2


source


Maybe you can close the closure function with another function that will call sleep () first?



0


source


The argument to the call alarm

is seconds, not minutes. Therefore, you are asking to wake up 5 seconds after each main cycle.

0


source


  • Try closing all file descriptors (including stdin and stdout). This should close the CGI instance if it is idle.
  • You can use select()

    with scheduling timeout instead of SIGALRM
0


source


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?

0


source


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.

0


source







All Articles