Здравствуйте. Отлаживаю свой демон. Перевод в режим демона делаю по книге «UNIX Профессиональное программирование Второе издание У. Ричард Стивенс, Стивен А. Раго»
как-то так:
int main(int argc, char *argv[]) {
...
// Перейти в режим демона.
daemonize(daemon_name);
// Убеждаемся, что нет запущенной копии
if (already_running(daemon_name, &fd_lock)) {
my_log(LOG_ERR, «daemon already running»);
return EXIT_FAILURE;
}
// Запуск рабочего тела демона
daemon(daemon_name);
// Закрываем файл, снимаем блокировку
close(fd_lock);
return EXIT_SUCCESS
}
void daemonize(const char *daemoName)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/*
** Сбросить маску режима создания файла.
*/
umask(0);
/*
* Получить максимально возможный номер дескриптора файла.
*/
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
err_quit(«%s: impossible to obtain the maximum number of descriptors.», daemoName);
/*
* Стать лидером новой сессии, чтобы утратить управляющий терминал.
*/
if ((pid = fork()) < 0)
err_quit(«%s: error function call fork», daemoName);
else if (pid != 0) /* родительский процесс */
exit(0);
setsid();
/*
* Обеспечить невозможность обретения управляющего терминала в будущем.
*/
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
err_quit(«%s: impossible to ignore the SIGHUP signal»);
if ((pid = fork()) < 0)
err_quit(«%s: error function call fork», daemoName);
else if (pid != 0) /* родительский процесс */
exit(0);
/*
* Назначить корневой каталог текущим рабочим каталогом,
* чтобы впоследствии можно было отмонтировать файловую систему.
*/
if (chdir(«/») < 0)
err_quit(«%s: impossible to make the current working directory /»);
/*
* Закрыть все открытые файловые дескрипторы.
*/
if (rl.rlim_max == RLIM_INFINITY)
rl.rlim_max = 1024;
for (i = 0; i < rl.rlim_max; i++)
close(i);
/*
* Присоединить файловые дескрипторы 0, 1 и 2 к /dev/null.
*/
fd0 = open(«/dev/null», O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
my_log(LOG_ERR, «wrong file descriptors %d %d %d», fd0, fd1, fd2);
exit(1);
}
}
int already_running(const char *daemoName, int *fd_lock)
{
int fd;
char buf[16];
char *pathname;
#define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
pathname = malloc(32);
memset(pathname, 0, 32);
sprintf(pathname,«/var/run/%s.pid»,daemoName);
fd = open(pathname, O_RDWR|O_CREAT, LOCKMODE);
if (fd < 0) {
printf(«do not open %s: %s\n», pathname, strerror(errno));
exit(1);
}
if (lockfile(fd) < 0) {
if (errno == EACCES || errno == EAGAIN) {
close(fd);
return(1);
}
printf(«do not set lock on %s: %s\n», pathname, strerror(errno));
exit(1);
}
ftruncate(fd, 0);
sprintf(buf, «%ld», (long)getpid());
write(fd, buf, strlen(buf));
// файл не закрывается, пока демон запущен.
*fd_lock = fd;
return(0);
}
int lockfile(int fd)
{
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_start = 0;
fl.l_whence = SEEK_SET;
fl.l_len = 0;
return(fcntl(fd, F_SETLK, &fl));
}
Вроде бы already_running запускается после daemonize, то есть после fork-а и после закрытия вех дескрипторов, но pid-файлы всё равно остаются не заблокированными на запись. Что может быть? Подскажите.