Pregunta

Estoy creando algunas aplicaciones FastCGI y me molesta que lighttpd no las elimine después de haber estado inactivas, así que estoy tratando de cerrarlas por sí solas.

Intenté usar

signal(SIGALRM, close);
alarm(300);

y hacer que la función de cierre ejecute exit(0), y eso funciona casi bien.

El problema es que se llama a la función de cierre cada vez que se ejecuta el bucle del programa principal (llamo a la alarma (300) en cada bucle para restablecerlo).He leído la página de manual de alarm() y no parece que llamarla varias veces con el mismo valor deba activar SIGALRM, así que supongo que Lighttpd está enviando una señal de alarma.

¡La gran pregunta!¿Hay alguna manera de ejecutar un método después de un intervalo específico y que ese intervalo se pueda restablecer sin SIGALRM?Sería bueno si también pudiera tener varias alarmas.

Aquí está toda la aplicación hasta el momento:

#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);
}
¿Fue útil?

Solución

la mejor manera es:agregue un hilo para que pueda eliminar la señal y la alarma, y ​​sincronice el hilo y su código principal (hilo principal).

Otros consejos

probablemente me utilizo temporizadores POSIX. Temporizadores no tienen que utilizar las señales. Usted tiene que elegir entre no notificar a todos, levantando una señal, o ejecutar una función como un nuevo hilo (que lo haría, ya que no interferirá con fastcgi).

Asegúrese de incluir <signal.h> y <time.h>, y el enlace con -lrt

En primer lugar, me llene su estructura 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
};

Ahora cree su contador de tiempo:

timer_t myTimer;
if(timer_create(CLOCK_REALTIME, &myTimerSignal, &myTimer)){
    //An error occurred, handle it
}

Lets armarlo, se llamará close () en un nuevo hilo en 300 segundos:

struct itimerspec timeUntilClose = {
    .it_value = {
        .tv_sec = 300 //300 seconds
    }
};

if(timer_settime(myTimer, 0, &timeUntilClose, NULL)){
    //Handle the error
}

Ahora, usted debe tener un temporizador preparado para detener el programa después de 300 segundos. Sé que podría llegar tarde, pero espero que esto ayuda a un lector futuro.

Tal vez se puede envolver la función de cierre por otra función que llamar primero al sueño ()?

El argumento para la llamada alarm es segundo , no minutos. Por lo que está pidiendo ser despertado en 5 segundos después de cada pasada por el bucle principal.

He aquí una solución que evita la especie de punto de la cuestión, pero funciona. Se responderá a sólo eventos de señal de mi aplicación:

void close(int intSignal, siginfo_t *info, void *context)
{
        // For some stupid reason MY signal doesn't populate siginfo_t
        if (!info)
        {
                count++;
        }
}

Si la estructura SIGINFO está vacía, eso es porque la alarma () se tropezó. Si un proceso fuera lo hace, siginfo_t.si_pid se rellena con cero.

Yo todavía no me gusta esta solución, pero funciona. algún que otro problema ahora es que hacer una salida (0) no se cierra la aplicación, aunque lighttpd piensa que se ha ido y genera otra. Esto significa que ahora tengo procesos rouge. raise(SIGUSR1) que es lo que se supone que debe dejar de guiones FastCGI no parece hacer el truco, ya sea ... hmmm ...

pregunta sigue siendo: ¿Cómo funciona funciones asíncronas una llamada en un temporizador de intervalos sin el uso de señales

?
  • Intente cerrar todos los descriptores de archivos (incluyendo entrada y salida estándar). Esto debe cerrar la instancia CGI si su inactividad.
  • Puede utilizar select() con tiempo de espera para programar en lugar de SIGALRM
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top