Question

Je construis des applications FastCGI et genre de bugs qui me lighttpd ne les tue pas au bout ils ont été au ralenti, donc je suis en train de les avoir près de leur propre chef.

J'ai essayé d'utiliser

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

et ayant la fonction de fermeture exécuter la sortie (0), et qui fonctionne presque bien.

Le problème est la fonction de fermeture est appelé à chaque fois que la boucle principale du programme fonctionne bien (je l'appelle alarme (300) chaque boucle pour le réinitialiser). J'ai lu la page de manuel pour l'alarme () et il ne semble pas que l'appeler plusieurs fois avec la même valeur devrait déclencher SIGALRM donc je suppose Lighttpd envoie un signal d'alarme.

La grande question! Y at-il un moyen d'exécuter une méthode après un intervalle spécifique, et ont cet intervalle sans être remis à zéro SIGALRM? Je serais bien si je pouvais avoir plusieurs alarmes aussi bien.

Voici l'application entière jusqu'ici:

#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);
}
Était-ce utile?

La solution

la meilleure façon est:. Ajouter un fil de sorte que vous pouvez supprimer le signal et l'alarme, et synchroniser le fil et votre code principal (fil conducteur)

Autres conseils

Je serais probablement utiliser des minuteries POSIX. Minuteries ne doivent pas utiliser les signaux. Vous avez le choix entre ne notifiant pas du tout, soulevant un signal, ou l'exécution d'une fonction comme un nouveau thread (que je le ferais car il ne gênera pas FastCGI).

Assurez-vous d'inclure <signal.h> et <time.h>, et le lien avec -lrt

D'abord, je rempliriez votre structure 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
};

Maintenant, créez votre minuterie:

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

permet d'armer, il appellera close () dans un nouveau thread en 300 secondes:

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

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

Maintenant, vous devriez avoir une minuterie prêt à arrêter le programme au bout de 300 secondes. Je sais que je peux être en retard, mais j'espère que cela aide un futur lecteur.

Peut-être que vous pouvez envelopper la fonction close par une autre fonction qui va d'abord appeler le sommeil ()?

L'argument à l'appel alarm est secondes , non minutes. Vous demandez donc d'être réveillé en 5 secondes après chaque passage dans la boucle principale.

Voici une solution qui évite en quelque sorte le point de la question, mais cela fonctionne. Il répondra aux seuls événements de signal de ma demande:

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 struct siginfo est vide, c'est parce que l'alarme () il trébuché. Si un processus externe le fait, siginfo_t.si_pid est peuplé de zéro.

Je n'aime toujours pas cette solution, mais il fonctionne. Odd problème est maintenant que faire une sortie (0) ne ferme pas l'application, bien que lighttpd pense qu'il est parti et engendre une autre. Cela signifie que maintenant j'ai processus de rouge. raise(SIGUSR1) qui est ce qui est censé arrêter des scripts FastCGI ne semble pas faire l'affaire soit ... hmmm ...

Question reste: Comment appelle-fonctions asynchrones sur une temporisation sans l'utilisation de signaux

?
  • Essayez de fermer tous les descripteurs de fichiers (y compris stdin et stdout). Cela devrait fermer l'instance de CGI si son ralenti.
  • Vous pouvez utiliser select() avec délai d'attente pour planifier au lieu de SIGALRM
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top