Вопрос

Я создаю несколько приложений FastCGI, и меня как бы беспокоит то, что Lighttpd не убивает их после простоя, поэтому я пытаюсь заставить их закрываться самостоятельно.

Я попробовал использовать

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

и функция закрытия выполняет выход (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
}

Давайте активируем его, он вызовет close() в новом потоке через 300 секунд:

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 думает, что оно исчезло, и порождает другое.Это значит, что теперь у меня румяные отростки. raise(SIGUSR1) то, что должно останавливать сценарии FastCGI, похоже, тоже не помогает...хм...

Вопрос все еще остается:Как вызвать асинхронные функции по интервальному таймеру без использования сигналов?

  • Попробуйте закрыть все файловые дескрипторы (включая stdin и stdout).Это должно закрыть экземпляр CGI, если он простаивает.
  • Вы можете использовать select() с таймаутом по расписанию вместо SIGALRM
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top