Frage

Ich baue einige FastCGI-Anwendungen und es irgendwie nervt mich, dass lighttpd sie fährt nicht töten, nachdem sie untätig waren, so versuche ich, sie auf ihre eigene Nähe zu haben.

Ich habe versucht mit

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

ist und die Schließfunktion Ausgang ausführen (0), und das funktioniert fast gut.

Das Problem ist die Schließfunktion der Hauptprogrammschleife läuft zwar jedes Mal aufgerufen wird (I Anruf Alarm (300) jeder Schleife es zurücksetzen). Ich habe den Mann Seite für Alarm () gelesen und es scheint nicht, als ob es mehrere Male mit dem gleichen Wert Aufruf sollte SIGALRM auslösen, damit ich Lighttpd gehe davon aus, ein Alarmsignal sendet.

Die große Frage! Gibt es eine Möglichkeit, ein Verfahren nach einem bestimmten Intervall zu laufen, und haben, dass ohne SIGALRM rücksetzbar sein Intervall? Ich wäre schön, wenn ich mehrere Alarme als auch haben könnte.

Hier ist die ganze App so weit:

#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);
}
War es hilfreich?

Lösung

der beste Weg ist. Einen Thread hinzufügen, so dass Sie Signal und Alarm entfernen können, und synchronisieren Sie den Faden und Ihren Hauptcode (Hauptthread)

Andere Tipps

Ich würde wahrscheinlich POSIX-Timer verwenden. Timer müssen keine Signale verwenden. Sie haben die Wahl zwischen nicht zu benachrichtigen, ein Signal Erhöhung oder eine Funktion als neuen Thread ausgeführt wird (was ich tun würde, da es nicht mit fastcgi stören).

Stellen Sie sicher, dass Sie umfassen <signal.h> und <time.h> und Link mit -lrt

Als erstes würde ich Ihre sigevent Struktur ausfüllen:

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

Jetzt erstellen Sie Ihre Timer:

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

Es läßt Arm-, wird es nennen close () in einem neuen Thread in 300 Sekunden:

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

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

Nun sollten Sie einen Timer bereit haben das Programm nach 300 Sekunden zu stoppen. Ich weiß, ich kann zu spät sein, aber ich hoffe, das hilft ein zukünftiger Leser.

Vielleicht können Sie die Close-Funktion durch eine andere Funktion wickeln die erste Schlaf nennen ()?

Das Argument des alarm Anruf Sekunden , nicht Minuten. So können Sie in 5 Sekunden nach jedem Mal durch die Hauptschleife aufgeweckt werden sind zu fragen.

Hier ist eine Lösung, die Art vermeidet die Stelle der Frage, aber es funktioniert. Es wird meine Anwendung reagiert nur Signalereignisse:

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

Wenn die siginfo Struktur leer ist, das ist, weil Alarm () es ausgelöst. Wenn ein externer Prozess ja, siginfo_t.si_pid mit Null aufgefüllt.

ich immer noch nicht, wie diese Lösung, aber es funktioniert. Odd Problem ist nun, dass eine Exit tun (0) schließt nicht die Anwendung, obwohl lighttpd denkt ist es weg und laicht eine andere. Das bedeutet, dass jetzt ich rouge Prozesse haben. raise(SIGUSR1) das ist, was zu stoppen FastCGI-Skripte sollte offenbar nicht den Trick tun: entweder ... hmmm ...

Frage bleibt: Wie nennt man asynchrone Funktionen auf einem Intervall-Timer, ohne die Verwendung von Signalen

  • Versuchen Sie, alle Datei-Deskriptoren (einschließlich stdin und stdout) zu schließen. Dies sollte die CGI-Instanz, wenn sein Leerlauf schließen.
  • Sie können select() mit Timeout anstelle von SIGALRM planen
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top