Domanda

Sto costruendo alcune applicazioni FastCGI ed è una sorta di bug me che lighttpd non ucciderli dopo essere stati di inattività, quindi sto cercando di averli vicino per conto proprio.

Ho provato ad utilizzare

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

e che ha la funzione stretta eseguire exit (0), e che funziona quasi bene.

Il problema è la funzione di chiusura viene chiamato ogni volta che il ciclo principale del programma viene eseguito anche se (che io chiamo di allarme (300) ogni loop per ripristinarlo). Ho letto la pagina man per l'allarme () e non sembra come se chiamandolo più volte con lo stesso valore dovrebbe inciampare SIGALRM così sto assumendo Lighttpd è l'invio di un segnale di allarme.

La grande domanda! C'è un modo per eseguire un metodo, dopo un intervallo specifico, e hanno quell'intervallo essere ripristinabile senza SIGALRM? Mi sarebbe bello se potessi avere più allarmi pure.

Ecco l'intera applicazione finora:

#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);
}
È stato utile?

Soluzione

il modo migliore è:. Aggiungere un filo in modo che è possibile rimuovere il segnale e di allarme, e sincronizzare il filo e il codice principale (thread principale)

Altri suggerimenti

probabilmente sarei utilizzare i timer POSIX. Timer non devono utilizzare segnali. Avete una scelta tra il non notificare a tutti, sollevando un segnale, o l'esecuzione di una funzione come un nuovo thread (che avrei fatto in quanto non interferirà con FastCGI).

Assicurati di includere <signal.h> e <time.h>, e il collegamento con -lrt

Per prima cosa, mi piacerebbe compilare la struttura 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
};

Ora crea il timer:

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

Permette la predispone, chiamerà close () in un nuovo filo in 300 secondi:

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

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

Ora, si dovrebbe avere un timer pronto a fermare il programma dopo 300 secondi. So che può essere in ritardo, ma spero che questo aiuta un lettore futuro.

Forse si può avvolgere la funzione di chiusura da un'altra funzione che prima chiamata sleep ()?

L'argomento per la chiamata alarm è secondi , non minuti. Quindi stai chiedendo di essere svegliato in 5 secondi dopo ogni volta attraverso il ciclo principale.

Ecco una soluzione che evita sorta di punto della questione, ma funziona. Si risponderà a solo gli eventi di segnale della mia applicazione:

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

Se la struct SIGINFO è vuoto, è perché allarme () scattato esso. Se un processo esterno fa, siginfo_t.si_pid è popolato con zero.

Ancora non mi piace questa soluzione, ma funziona. problema Odd ora è che facendo un'uscita (0) non chiude l'applicazione, anche se lighttpd pensa che sia andato e genera un'altra. Ciò significa che ora ho processi rouge. raise(SIGUSR1) che è quello che dovrebbe fermare gli script FastCGI non sembra fare il trucco o ... hmmm ...

Domanda ancora rimane: come si fa a chiamata funzioni asincrone su un timer a intervalli, senza l'uso di segnali

?
  • Prova a chiudere tutti i descrittori di file (tra cui stdin e stdout). Questo dovrebbe chiudere l'istanza CGI se inattivo.
  • È possibile utilizzare select() con timeout per programmare al posto di SIGALRM
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top