С демоном сна () - PullRequest
       27

С демоном сна ()

2 голосов
/ 01 сентября 2010

Я запускаю простой демон-тест в c ++. Он работает нормально без функции sleep (), но если я добавлю функцию sleep (), он запустится один раз и останется в режиме сна. Кроме того, при первом запуске в файле logs / log.dat должен быть напечатан один раз «Hello», но этого также не происходит. Вот код:

 #include <cstdlib>  
 #include <cstdio>  
 #include <iostream>  
 #include <unistd.h>  
 using namespace std;  
 int main(int argc, char** argv) {  
    FILE *f = NULL;   
    if ((f = fopen("logs/log.dat  ", "w")) != NULL) {  
        if (daemon(0, 0) >= 0) {  
            while (true) {  
                fprintf(f, "%s\n", "Hello");  
                sleep(5);  
            }  
        } else {  
            fprintf(f, "%s\n", "Error detaching terminal");  
        }  
    } else {  
        printf("%s\n", "Cannot open log file");  
    }  
    return 0;  
}

Ответы [ 3 ]

5 голосов
/ 01 сентября 2010

Попробуйте добавить fflush () после вашего fprintf ().Возможно, он работает, но еще не записал данные на диск.

3 голосов
/ 01 сентября 2010

Что входит в функцию daemon()?В частности, закрывает ли он открытые файлы, кроме стандартного ввода, стандартного вывода и стандартной ошибки?Если это так, то последующие операторы fprintf() завершатся неудачно, поскольку файл, который был открыт до того, как вы вызвали daemon(), впоследствии будет закрыт.

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

Самый быстрый способ проверить эту гипотезу - открыть журналфайл после демонизации.

Обратите внимание, что некоторые подпрограммы daemon() тоже меняют каталог - обычно на корневой каталог.Это вызвало бы головную боль при относительном пути к файлу журнала.


В MacOS X функция daemon(3) снабжена объявлением в <stdlib.h>;Кажется, он был представлен в BSD 4.4:

SYNOPSIS

#include <stdlib.h>

 int
 daemon(int nochdir, int noclose);

ОПИСАНИЕ

Функция daemon () предназначена для программ, желающих отсоединиться отуправляющий терминал и работающий в фоновом режиме как системные демоны.[...]

Если аргумент nochdir не равен нулю, daemon () изменяет текущий рабочий каталог на корень (/).

Если аргумент noclose не равен нулю,daemon () перенаправит стандартный ввод, стандартный вывод и стандартную ошибку в /dev/null.


Вы можете проверить исходный код FreeBSD 8 .

Так как вызов daemon() дважды передает 0, код выполняет chdir("/"), и он повторно соединяет файловые дескрипторы 0, 1, 2 с '/ dev / null'.Страница руководства продолжает обсуждать fork(2) и setsid(2).Таким образом, мы можем быть достаточно уверены, что в вашей программе стандартные каналы ввода-вывода подключены к / dev / null, а текущий каталог изменен на корневой каталог.

На странице руководства упоминается, что вам следует соблюдать осторожность.чтобы любые открытые файлы имели дескриптор файла больше 2, чтобы избежать проблем.Можете ли вы напечатать «fileno (f)» где-нибудь - это целое число - и убедиться, что оно больше 2. Если оно недостаточно велико, то это является причиной вашей проблемы;не вызывайте вашу программу с уже закрытыми stdin, stdout или stderr.

Это еще не объясняет отсутствие данных в файле и почему sleep() влияет на результат.Конечно, классическая реализация sleep() скрипок с сигналами и SIGALRM;на странице руководства для daemon(3) упоминается SIGHUP.Однако реализация FreeBSD 8 sleep(3) использует системный вызов nanosleep(2).

Итак, я согласен с предложением Джея - файл будет полностью буферизован, и вам придется ждать большогоколичество 5-секундных циклов для печати достаточного количества данных для очистки буфера (для этого может потребоваться 4096 байт, при 6 байтах за 5 секунд, потребуется около часа для создания чего-либо в файле).Добавление fflush(), скорее всего, решит проблему отсутствия сообщения.Либо используйте setvbuf(f, 0, _IONBF, 0);, чтобы отключить всю буферизацию, или setvbuf(f, 0, _IOLBF, BUFSIZ);, чтобы включить буферизацию строки.И sleep() является фактором просто потому, что он сильно замедляет обработку.

0 голосов
/ 27 декабря 2014

У меня была похожая проблема, но поскольку я использовал syslog, использование fflush () было невозможно.В моем случае решение было изменить сообщение отладки.

С:

syslog(LOG_DEBUG, "DEBUG: tick");

Кому:

syslog(LOG_DEBUG, "DEBUG: tick %d", i); // i is increased in the loop

, чтобы каждый раз было другое сообщение.

...