gpt4 book ai didi

c - fcntl F_GETLK 总是返回真

转载 作者:太空宇宙 更新时间:2023-11-03 23:47:39 27 4
gpt4 key购买 nike

我正在尝试使用锁定文件创建单个实例守护进程,但 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 写入其中!

我做错了什么?第二个实例不应该在 get_lock_file_status 中返回 -1 吗?

最佳答案

您正在以错误的方式检查 F_GETLK 的结果。 fcntl(2) with F_GETLK 仅在出错时返回 -1。检查是否有可能获取锁的正确方法是检查 struct flockl_type 字段是否设置为 F_UNLCK ,如下所示:

/* try locking pid file*/
if(fcntl(pid_fd, F_GETLK, &pid_lck) == -1) {
syslog (LOG_ERR, "Unhandled error ocured while locking PID file > [Errno: %s]", strerror(errno));
close(pid_fd);
return -1;
}
close(pid_fd);
return (pid_lck.l_type == F_UNLCK) ? 0 : -1;

应该可以将 creat_lock_file()get_lock_file_status() 滚动到一个打开文件的函数中(如果文件不存在则创建它),尝试对其设置锁定,并返回锁定是否成功(例如,文件描述符或 -1)。

顺便说一下,在将 PID 写入其中之前,您应该截断 (2) PID 文件为零字节。假设您进程的 PID 是 5,而 PID 文件中的旧 PID 是 123。写入“5”将使 PID 文件的内容变为“523”。将文件截断为零字节可解决此问题。 (O_TRUNC 将不起作用,因为您在打开文件以测试是否设置了锁定时会清除该文件。)

在程序退出时使用 unlink(2) 删除 PID 文件也很常见。这样,文件不存在表明守护进程没有运行(尽管它不是万无一失的,因为进程或系统可能会崩溃)。

关于c - fcntl F_GETLK 总是返回真,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29042348/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com