문제

저는 일부 FastCGI 앱을 만들고 있는데 lighttpd가 유휴 상태가 된 후에도 앱을 종료하지 않는다는 점이 좀 아쉽습니다. 그래서 앱을 스스로 닫으려고 합니다.

나는 사용해 보았다.

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

그리고 닫기 함수가 exit(0)을 실행하도록 하면 거의 잘 작동합니다.

문제는 메인 프로그램 루프가 실행될 때마다 닫기 함수가 호출된다는 것입니다(저는 루프를 재설정하기 위해 각 루프마다 알람(300)을 호출합니다).나는 Alarm()에 대한 매뉴얼 페이지를 읽었으며 동일한 값으로 여러 번 호출해도 SIGALRM이 작동하지 않는 것 같으므로 Lighttpd가 경보 신호를 보내고 있다고 가정합니다.

큰 질문입니다!특정 간격 후에 메소드를 실행하고 SIGALRM 없이 해당 간격을 재설정할 수 있는 방법이 있습니까?알람도 여러 개 있으면 좋을 것 같아요.

지금까지의 전체 앱은 다음과 같습니다.

#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);
}
도움이 되었습니까?

해결책

가장 좋은 방법은 다음과 같습니다. 스레드를 추가하여 신호 및 알람을 제거하고 스레드와 기본 코드 (기본 스레드)를 동기화 할 수 있습니다.

다른 팁

아마 POSIX 타이머를 사용할 것입니다. 타이머는 신호를 사용할 필요가 없습니다. 전혀 알리지 않거나 신호를 올리거나 기능을 새로운 스레드로 실행하는 것 중에서 선택할 수 있습니다 (FastCGI를 방해하지 않기 때문에 수행 할 것입니다).

포함하십시오 <signal.h> 그리고 <time.h>, 그리고 링크 -lrt

먼저, 나는 당신의 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
};

이제 타이머를 만듭니다.

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

무기를 들으면 300 초 안에 새 스레드로 Close ()를 호출합니다.

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

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

이제 300 초 후에 프로그램을 중지 할 타이머가 있어야합니다. 나는 늦을지도 모르지만 이것이 미래의 독자에게 도움이되기를 바랍니다.

먼저 sleep ()를 호출하는 다른 함수로 가까운 기능을 감을 수 있습니까?

에 대한 논쟁 alarm 전화입니다 , 몇 분이 아닙니다. 그래서 당신은 메인 루프를 통해 매번 5 초 후에 깨어날 것을 요구합니다.

다음은 질문의 요점을 피하는 일종의 솔루션이지만 작동합니다.내 애플리케이션의 신호 이벤트에만 응답합니다.

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

siginfo 구조체가 비어 있다면, 이는 알람()이 이를 작동시켰기 때문입니다.외부 프로세스가 이를 수행하는 경우 siginfo_t.si_pid는 0으로 채워집니다.

나는 여전히 이 솔루션이 마음에 들지 않지만 작동합니다.이제 이상한 문제는 lighttpd가 응용 프로그램이 사라졌다고 생각하고 다른 응용 프로그램을 생성하더라도 Exit(0)을 수행해도 응용 프로그램이 닫히지 않는다는 것입니다.이것은 이제 루즈한 프로세스가 있다는 것을 의미합니다. raise(SIGUSR1) 이는 FastCGI 스크립트를 중지하기로 되어 있는 것인데도 트릭을 수행하지 않는 것 같습니다...흠...

여전히 질문이 남아 있습니다.신호를 사용하지 않고 간격 타이머에서 비동기 함수를 어떻게 호출합니까?

  • 모든 파일 설명자 (stdin 및 stdout 포함)를 닫으십시오. 유휴 상태 인 경우 CGI 인스턴스를 닫습니다.
  • 당신이 사용할 수있는 select() sigalrm 대신 일정 시간을 정리합니다
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top