Я пытаюсь создать демон с одним экземпляром, используя файл блокировки, но fcntl()
не работает должным образом...
int creat_lock_file (char * pid_fn)
{
struct flock pid_lck = {F_WRLCK, SEEK_SET, 0, 0, 0 };
/* Open/Create pid file */
int pid_fd = open (pid_fn, O_CREAT | O_WRONLY, 0640);
if (pid_fd == -1)
{
syslog (LOG_ERR, "Unable to open PID file > [Errno: %s]", strerror(errno));
return -1;
}
/* Place write lock on pid file */
if (fcntl(pid_fd, F_SETLK, &pid_lck) == -1) {
/* Unhandled error ocured */
syslog (LOG_ERR, "Unhandled error ocured while locking PID file > [Errno: %s]", strerror(errno));
close (pid_fd);
return -1;
}
/* Write PID to lock file */
char pid_lock_buf[11];
sprintf (pid_lock_buf, "%ld\n", (long) getpid ());
write (pid_fd, pid_lock_buf, strlen (pid_lock_buf)+1);
return 0;
}
int get_lock_file_status (char * pid_fn)
{
struct flock pid_lck = {F_WRLCK, SEEK_SET, 0, 0, 0 };
/* Open/Create pid file */
int pid_fd = open (pid_fn, O_CREAT | O_WRONLY, 0640);
if (pid_fd == -1)
{
syslog (LOG_ERR, "Unable to open PID file > [Errno: %s]", strerror(errno));
return -1;
}
/* try locking pid file*/
if(fcntl(pid_fd, F_GETLK, &pid_lck) == -1)
{
if(errno == EAGAIN || errno == EACCES) /* file already locked, close fd and return -1 */
{
close (pid_fd);
return -1;
}
else /* Unhandled error ocured */
{
syslog (LOG_ERR, "Unhandled error ocured while locking PID file > [Errno: %s]", strerror(errno));
close (pid_fd);
return -1;
}
}
close (pid_fd);
return 0;
}
поэтому я вызываю get_lock_file_status
и выхожу, если он возвращает -1, чтобы убедиться, что никакой другой экземпляр не запущен, кроме того, что я делаю некоторые вещи (fork chdir и т. д.) и вызываю creat_lock_file
для создания ящика и блокировки файла pid после успешного создания демона...
при выполнении и запуске программа работает так, как ожидалось, запускает создает файл блокировки и записывает в него pid, но когда второй экземпляр запускается, второй экземпляр просто открывает тот же файл блокировки и записывает в него свой собственный pid!
Что я делаю не так? разве второй экземпляр не должен возвращать -1 в get_lock_file_status
?
fcntl(2)
сF_SET/GET/LK
в порядке, а также POSIX, аflock(2)
— нет (хотя он широко доступен). Эти два метода имеют различное поведение w.r.t. блокировка наследования и некоторые другие вещи.fcntl()
может устанавливать блокировки на области файлов, аflock()
не может. - person Ulfalizer   schedule 14.03.2015