Базовая обработка сигналов в С++

Это довольно простой сценарий, но я не нахожу слишком много полезных ресурсов. У меня есть программа на С++, работающая в Linux, которая обрабатывает файлы. Читает строки, выполняет различные преобразования, записывает данные в базу данных. Существуют определенные переменные (хранящиеся в базе данных), которые влияют на обработку, которую я сейчас читаю на каждой итерации, потому что я хочу, чтобы обработка была как можно более актуальной, но небольшое отставание в порядке. Но эти переменные меняются довольно редко, и чтение со временем дорого (10 миллионов плюс строки в день). Я мог бы пропустить прочитанные на каждую n-итерацию или просто перезапустить программу, когда переменная изменяется, но это кажется хакерским.

Вместо этого я хочу, чтобы программа запускала перечитывание переменных при получении SIGHUP. Все, что я читаю о обработке сигналов, говорит о библиотеке сигналов С, и я не уверен, как привязываться к моим классам программ. Библиотеки сигналов Boost, похоже, больше связаны с межобъектной связью, а не с сигналами ОС.

Может ли кто-нибудь помочь? Похоже, это должно быть невероятно просто, но я довольно ржавый с С++.

Ответ 1

Я бы справился с этим так же, как вы могли бы обработать его в C. Я считаю, что совершенно нормально иметь автономную функцию обработчика сигнала, поскольку вы просто отправляете ее в семафор или устанавливаете переменную или некоторые такие, которые другой поток или объект могут проверить, нужно ли перечитывать настройки.

#include <signal.h>
#include <stdio.h>

/* or you might use a semaphore to notify a waiting thread */
static volatile sig_atomic_t sig_caught = 0;

void handle_sighup(int signum) 
{
    /* in case we registered this handler for multiple signals */ 
    if (signum == SIGHUP) {
        sig_caught = 1;
    }
}

int main(int argc, char* argv[]) 
{
    /* you may also prefer sigaction() instead of signal() */
    signal(SIGHUP, handle_sighup);

    while(1) {
        if (sig_caught) {
            sig_caught = 0;
            printf("caught a SIGHUP.  I should re-read settings.\n");
        }
    }

    return 0;
}

Вы можете протестировать отправку SIGHUP с помощью kill -1 `pidof yourapp`.

Ответ 2

Я бы рекомендовал проверить эту ссылку, которая дает информацию о регистрации сигнала.

Если я ошибаюсь, важно помнить, что любая функция внутри объекта ожидает параметр референта, что означает, что нестатические функции-члены не могут быть обработчиками сигналов. Я считаю, что вам нужно зарегистрировать его либо в статической функции-члене, либо в какой-то глобальной функции. Оттуда, если у вас есть определенная функция объекта, которую вы хотите позаботиться о своем обновлении, вам понадобится способ ссылки на этот объект.

Ответ 3

Существует несколько возможностей; это не обязательно будет излишним для реализации всех из них:

  • Отвечайте на конкретный сигнал, как и на C. С++ работает одинаково. См. Документацию для signal().
  • Триггер на временной отметке изменения некоторого изменения файла, например, базы данных, если он хранится в плоском файле.
  • Триггер один раз в час или один раз в день (что имеет смысл).

Ответ 4

Вы можете определить сигнал усиления, соответствующий сигналу ОС, и связать сигнал усиления с вашим слотом, чтобы вызвать соответствующий обработчик.