Unix - статьи


         

Демоны - часть 5


Функция-обработчик FatalSigHandler() записывает в журнал событий информацию о полученном сигнале, и затем завершает процесс, вызвав перед этим функции closelog() и TidyUp(), которые высвобождают все занятые процессом ресурсы: void FatalSigHandler(int sig) { #ifdef _GNU_SOURCE syslog(LOG_LOCAL0|LOG_INFO,"caught signal: %s – exiting",strsignal(sig)); #else syslog(LOG_LOCAL0|LOG_INFO,"caught signal: %d – exiting",sig); #endif closelog(); TidyUp(); _exit(0); }

На те три сигнала, которые относятся к категории обрабатываемых, – SIGTERM, SIGUSR1 и SIGHUP, демон реагирует по-разному: sigtermSA.sa_handler = TermHandler; sigemptyset(&sigtermSA.sa_mask); sigtermSA.sa_flags = 0; sigaction(SIGTERM, &sigtermSA, NULL); sigusr1SA.sa_handler = Usr1Handler; sigemptyset(&sigusr1SA.sa_mask); sigusr1SA.sa_flags = 0; sigaction(SIGUSR1, &sigusr1SA, NULL); sighupSA.sa_handler = HupHandler; sigemptyset(&sighupSA.sa_mask); sighupSA.sa_flags = 0; sigaction(SIGHUP, &sighupSA, NULL);

Обработчик TermHandler() вызывает функцию TidyUp() и завершает процесс. Обработчик Usr1Handler() делает в системном журнале запись о вежливом завершении процесса и присваивает переменной gGracefulShutdown значение 1 (что, как вы помните, приводит к выходу из цикла обработки запросов, когда цикл будет готов к этому). Обработчик сигнала HupHandler() также делает запись в системном журнале, после чего присваивает значение 1 переменным gGracefulShutdown и gCaughtHupSignal. В реальной жизни получение сигнала SIGHUP приводит к перезапуску демона, который сопровождается повторным прочтением файла конфигурации (который обычно читается демоном именно во время запуска) и переустановкой значений записанных в нем параметров. Именно необходимость прочесть повторно файл конфигурации является наиболее частой причиной перезапуска демонов. У нашего демона файла конфигурации нет, так что в процессе перезапуска делать ему особенно нечего.

Обратите внимание на тип переменных gGracefulShutdown и gCaughtHupSignal. С типом sig_atomic_t мы раньше не встречались. Применение этого типа гарантирует, что чтение и запись данных в переменные gGracefulShutdown и gCaughtHupSignal будет выполняться атомарно, одной инструкцией процессора, которая не может быть прервана. Атомарность при работе с переменными gGracefulShutdown и gCaughtHupSignal важна потоуму, что к ним могут одновременно получить доступ и обработчики сигналов, и главная функция программы. По этой же причине мы помечаем указанные переменные ключевым словом volatile.

Функция BindPassiveSocket() открывает для прослушивания порт сервера (в нашем случае это порт 30333) на всех доступных сетевых интерфейсах и возвращает соответствующий сокет: int BindPassiveSocket(const int portNum, int *const boundSocket) { struct sockaddr_in sin; int newsock, optval; size_t optlen; memset(&sin.sin_zero, 0, 8); sin.sin_port = htons(portNum); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); if((newsock= socket(PF_INET, SOCK_STREAM, 0))




Содержание  Назад  Вперед