int TDaemon::WorkProc() { struct sigaction sigact; sigset_t sigset; int signo; int status; // сигналы об ошибках в программе будут обрататывать более тщательно // указываем что хотим получать расширенную информацию об ошибках sigact.sa_flags = SA_SIGINFO; // задаем функцию обработчик сигналов sigact.sa_sigaction = SelfDebug; sigemptyset(&sigact.sa_mask); // установим наш обработчик на сигналы sigaction(SIGFPE, &sigact, 0); // ошибка FPU sigaction(SIGILL, &sigact, 0); // ошибочная инструкция sigaction(SIGSEGV,&sigact, 0); // ошибка доступа к памяти sigaction(SIGBUS, &sigact, 0); // ошибка шины, при обращении к физической памяти sigemptyset(&sigset); // блокируем сигналы которые будем ожидать // сигнал остановки процесса пользователем sigaddset(&sigset, SIGQUIT); // сигнал для остановки процесса пользователем с терминала sigaddset(&sigset, SIGINT); // сигнал запроса завершения процесса sigaddset(&sigset, SIGTERM); // пользовательский сигнал который мы будем использовать для обновления конфига sigaddset(&sigset, SIGHUP); sigprocmask(SIG_BLOCK, &sigset, NULL); // Установим максимальное кол-во дискрипторов которое можно открыть SetFdLimit(FD_LIMIT); // запишем в лог, что наш демон стартовал //WriteLog("%s [DAEMON] Started\n", getTime()); DaemonFunction(); // цикл ожидания сообщений while(1) { // ждем указанных сообщений sigwait(&sigset, &signo); switch(signo) { // если это сообщение обновления конфига case SIGHUP: status = ReloadConfig(); if (status != 0) { WriteLog("%s [DAEMON] Reload config failed: %s\n", getTime(),strerror(errno)); } else { WriteLog("%s [DAEMON] Reload config OK\n", getTime()); } break; case SIGQUIT: case SIGINT: case SIGTERM: default: WriteLog("%s [DAEMON] Received signal %d\n", getTime(),signo); WriteLog("%s [DAEMON] Stopped\n", getTime()); return CHILD_NEED_TERMINATE; } } WriteLog("%s [DAEMON] Stopped\n", getTime()); // вернем код не требующим перезапуска return CHILD_NEED_TERMINATE; }
int WorkProc() { struct sigaction sigact; sigset_t sigset; int signo; int status; // сигналы об ошибках в программе будут обрататывать более тщательно // указываем что хотим получать расширенную информацию об ошибках sigact.sa_flags = SA_SIGINFO; // задаем функцию обработчик сигналов sigact.sa_sigaction = signal_error; sigemptyset(&sigact.sa_mask); // установим наш обработчик на сигналы sigaction(SIGFPE, &sigact, 0); // ошибка FPU sigaction(SIGILL, &sigact, 0); // ошибочная инструкция sigaction(SIGSEGV, &sigact, 0); // ошибка доступа к памяти sigaction(SIGBUS, &sigact, 0); // ошибка шины, при обращении к физической памяти sigemptyset(&sigset); // блокируем сигналы которые будем ожидать // сигнал остановки процесса пользователем sigaddset(&sigset, SIGQUIT); // сигнал для остановки процесса пользователем с терминала sigaddset(&sigset, SIGINT); // сигнал запроса завершения процесса sigaddset(&sigset, SIGTERM); // пользовательский сигнал который мы будем использовать для обновления конфига sigaddset(&sigset, SIGUSR1); sigprocmask(SIG_BLOCK, &sigset, NULL); // Установим максимальное кол-во дискрипторов которое можно открыть SetFdLimit(FD_LIMIT); // запишем в лог, что наш демон стартовал WriteLog("[DAEMON] Started\n"); // запускаем все рабочие потоки status = InitWorkThread(); if (status != -1) { // цикл ожижания сообщений for (; ;) { // ждем указанных сообщений sigwait(&sigset, &signo); // если то сообщение обновления конфига if (signo == SIGUSR1) { // обновим конфиг status = ReloadConfig(); if (status == 0) { WriteLog("[DAEMON] Reload config failed\n"); } else { WriteLog("[DAEMON] Reload config OK\n"); } } else // если какой-либо другой сигнал, то выйдим из цикла { break; } } // остановим все рабочеи потоки и корректно закроем всё что надо DestroyWorkThread(); } else { WriteLog("[DAEMON] Create work thread failed\n"); } WriteLog("[DAEMON] Stopped\n"); // вернем код не требующим перезапуска return CHILD_NEED_TERMINATE; }