LINUX.ORG.RU

Не блокируется pid-файл

 ,


1

3

Здравствуйте. Отлаживаю свой демон. Перевод в режим демона делаю по книге «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-файлы всё равно остаются не заблокированными на запись. Что может быть? Подскажите.



Последнее исправление: leonopulos (всего исправлений: 2)

1. Открой для себя LORCODE
2. Простыни текста выкладывай на pastebin
3. Мне лень в таком жутком форматировании что-то читать, поэтому могу предложить почитать мое

Eddy_Em ☆☆☆☆☆
()
NAME
       daemon - run in the background

SYNOPSIS
       #include <unistd.h>

       int daemon(int nochdir, int noclose);

   Feature Test Macro Requirements for glibc (see feature_test_macros(7)):

       daemon(): _BSD_SOURCE || (_XOPEN_SOURCE && _XOPEN_SOURCE < 500)

DESCRIPTION
       The daemon() function is for programs wishing to detach themselves from
       the controlling terminal and run in the background as system daemons.
imb ★★
()

спасибо. отладился уже.

leonopulos
() автор топика

Код особо не смотрел, но ты уверен, что у тебя после fork() в дочернем процессе все функции async-signal-safe? Быть может, как-то связано.

После форка следует в дочернем процессе подготовить файловые дескрипторы, а потом загрузить новый образ через exec. В макоси хороший ман у fork() на эту тему. В линуксе - как-то мутновато.

dave ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.