Что находится в функции daemon()? В частности, закрывает ли он открытые файлы, кроме стандартного ввода, стандартного вывода и стандартной ошибки? Если это так, то последующие операторы fprintf() завершатся ошибкой, потому что файл, который был открыт до того, как вы вызвали daemon(), впоследствии закрывается.
Если бы ваш код проверял возвращаемые значения из функций печати, вы могли бы это выяснить (хотя вам, вероятно, придется открыть файл журнала с абсолютным путем, чтобы иметь возможность сообщить об этом из демонизированного процесса).
Самый быстрый способ проверить эту гипотезу — открыть файл журнала после демонизации.
Обратите внимание, что некоторые подпрограммы daemon() также меняют каталог - обычно в корневой каталог. Это вызовет у вас головную боль с относительным путем к файлу журнала.
В MacOS X функция daemon(3) предоставляется с объявлением в <stdlib.h>; он был представлен в BSD 4.4, кажется:
СИНТАКСИС
#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. Однако реализация sleep(3) во FreeBSD 8 использует системный вызов nanosleep(2).
Итак, я собираюсь согласиться с предложением Джея — файл будет полностью буферизован, и вам придется ждать большого количества 5-секундных циклов, чтобы напечатать достаточно данных для очистки буфера (для этого может потребоваться 4096 байтов при 6 байтах). за 5 секунд, потребуется около часа, чтобы создать что-либо в файле). Добавление fflush(), скорее всего, решит проблему «неотображения сообщения». В качестве альтернативы используйте setvbuf(f, 0, _IONBF, 0);, чтобы отключить всю буферизацию, или setvbuf(f, 0, _IOLBF, BUFSIZ);, чтобы включить буферизацию строк. И sleep() является фактором просто потому, что он сильно замедляет обработку.
01.09.2010