Как перезапустить программу-демон C в Linux после получения сигнала SIGHUP - PullRequest
7 голосов
/ 02 июня 2010

Может кто-нибудь опубликовать пример кода о том, как я могу перечитать файл конфигурации и перезапустить мой демон после того, как демон получит сигнал SIGHUP. Демон - это программа пространства пользователя, написанная на C на Linux и не запускаемая inetd.

Ответы [ 4 ]

6 голосов
/ 02 июня 2010

В зависимости от того, насколько четко написана ваша программа, есть (как минимум) три способа сделать это:

  1. При получении сигнала вернитесь к началу программы перед фазой инициализации (возможно - но не обязательно - через пару setjmp () / longjmp () или sigsetjmp () / siglongjmp ()) , таким образом сбрасывая и перечитывая файл конфигурации.

  2. После получения сигнала обработчик сигнала снова должен выполнить исходную программу. Это имеет преимущество потери всего состояния и сброса всех глобальных и статических переменных обратно в их исходное состояние. У него есть недостаток потери всего предыдущего состояния.

  3. Третий вариант, возможно, менее жестокий; было бы отмечено, что сигнал был получен, и в следующей удобной точке основного цикла обработки вернется и перечитает файл конфигурации.

То, что работает, частично зависит от того, что должен делать ваш демон. Если он проводит время в разговоре со своими клиентами, вы можете не захотеть использовать ни один из вариантов 1 или 2 - вы бы предпочли использовать вариант 3. Если вы делаете одноразовые ответы на простые вопросы, жестокие подходы могут быть эффективный (и, вероятно, проще для программирования). Обратите внимание, что вариант 1 требует осторожного обращения с WIP (работа в процессе) и такими вещами, как открытые файлы - если вы не будете осторожны, вы потеряете отслеживание ресурсов, и демон выйдет из строя (из памяти, из файловых дескрипторов) скорее всего один из этих двух).

1 голос
/ 24 мая 2013

Другой, немного более сложный пример, здесь:

http://man7.org/tlpi/code/online/dist/daemons/daemon_SIGHUP.c.html

1 голос
/ 05 ноября 2010

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

volatile sig_atomic_t g_eflag = 0;
volatile sig_atomic_t g_hupflag = 1;

static void signal_handler(int sig)
{
    switch(sig)
    {
    case SIGHUP:
        g_hupflag = 1;
        break;
    case SIGINT:
    case SIGTERM:
        g_eflag = 1;
        break;
    }
}

int main(int argc, char **argv)
{
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGHUP, signal_handler);
    signal(SIGPIPE, SIG_IGN);

    while(!g_eflag)
    {
        if(g_hupflag)
        {
            g_hupflag = 0;
            load_config();
        }

        // ... do daemon work ...
    }

    return 0;
}
0 голосов
/ 03 июня 2010

Зависит от того, как вы это структурируете;если вы обрабатываете несколько соединений в одном потоке / процессе, то вам, вероятно, следует как-то уведомить их о выходе (если вы можете; зависит от протокола) перед перезагрузкой конфигурации (или самого exec).

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

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

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

...