Pergunta

Estou construindo alguns aplicativos fastcgi e isso me incomoda que o LightTPD não os mate depois de estarem ociosos, então estou tentando tê -los por si só.

Eu tentei usar

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

e ter a função fechada executa a saída (0), e isso funciona quase bem.

O problema é que a função de fechamento está sendo chamada toda vez que o loop do programa principal é executado (eu chamo de alarme (300) cada loop para redefini -lo). Eu li a página do homem para o alarme () e não parece que chamá -lo várias vezes com o mesmo valor deve tropeçar no SigalRM, por isso estou assumindo que o LightTPD está enviando um sinal de alarme.

A grande questão! Existe uma maneira de executar um método após um intervalo específico e ter esse intervalo ser reastável sem Sigalrm? Eu seria legal se eu pudesse ter vários alarmes também.

Aqui está todo o aplicativo até agora:

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

Solução

A melhor maneira é: adicione um encadeamento para que você possa remover sinal e alarme e sincronizar o encadeamento e seu código principal (encadeamento principal).

Outras dicas

Eu provavelmente usaria temporizadores POSIX. Os temporizadores não precisam usar sinais. Você tem uma opção entre não notificar, levantar um sinal ou executar uma função como um novo encadeamento (o que eu faria, pois não interferirá no FastCGI).

Certifique -se de incluir <signal.h> e <time.h>, e vincular -se a -lrt

Primeiro, eu preencheria sua estrutura sigvent:

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

Agora crie seu cronômetro:

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

Vamos armar, ele ligará para fechar () em um novo tópico em 300 segundos:

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

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

Agora, você deve ter um cronômetro pronto para interromper o programa após 300 segundos. Sei que posso estar atrasado, mas espero que isso ajude um futuro leitor.

Talvez você possa embrulhar a função Fechar por outra função que primeiro chamará o Sleep ()?

O argumento para o alarm Chamada é segundos, não minutos. Então, você está pedindo para ser acordado em 5 segundos após cada vez no loop principal.

Aqui está uma solução que meio que evita o ponto da pergunta, mas funciona. Ele responderá apenas aos eventos de sinal do meu aplicativo:

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

Se a estrutura Siginfo estiver vazia, isso é porque o alarme () a tropeçou. Se um processo externo o fizer, o SIGINFO_T.SI_PID será preenchido com zero.

Ainda não gosto dessa solução, mas funciona. O problema estranho agora é que fazer uma saída (0) não fecha o aplicativo, embora o LightTPD pense que ela se foi e gera outro. Isso significa que agora eu tenho processos Rouge. raise(SIGUSR1) O que é o que deve parar os scripts fastcgi também não parece fazer o truque ... hmmm ...

Pergunta ainda permanece: como se chama funções assíncronas em um cronômetro de intervalo sem o uso de sinais?

  • Tente fechar todos os descritores de arquivo (incluindo stdin e stdout). Isso deve fechar a instância do CGI se estiver ocioso.
  • Você pode usar select() com tempo limite para agendar em vez de sigalrm
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top