gpt4 book ai didi

c - 使用 dup2 时的竞争条件

转载 作者:IT王子 更新时间:2023-10-29 00:26:37 27 4
gpt4 key购买 nike

This manpage对于 dup2 系统调用说:

EBUSY (Linux only) This may be returned by dup2() or dup3() during a race condition with open(2) and dup().

它讨论的竞争条件是什么?如果 dup2 出现 EBUSY 错误,我该怎么办?我应该像 EINTR 那样重试吗?

最佳答案

fs/file.c中有解释,do_dup2() :

/*
* We need to detect attempts to do dup2() over allocated but still
* not finished descriptor. NB: OpenBSD avoids that at the price of
* extra work in their equivalent of fget() - they insert struct
* file immediately after grabbing descriptor, mark it larval if
* more work (e.g. actual opening) is needed and make sure that
* fget() treats larval files as absent. Potentially interesting,
* but while extra work in fget() is trivial, locking implications
* and amount of surgery on open()-related paths in VFS are not.
* FreeBSD fails with -EBADF in the same situation, NetBSD "solution"
* deadlocks in rather amusing ways, AFAICS. All of that is out of
* scope of POSIX or SUS, since neither considers shared descriptor
* tables and this condition does not arise without those.
*/
fdt = files_fdtable(files);
tofree = fdt->fd[fd];
if (!tofree && fd_is_open(fd, fdt))
goto Ebusy;

看起来像 EBUSY 当要释放的描述符处于某种不完整状态时它仍在打开时返回(fd_is_open 但不存在于 fdtable )。

编辑(更多信息并想要赏金)

为了理解 !tofree && fd_is_open(fd, fdt) 是如何发生的,让我们看看文件是如何打开的。这是 sys_open 的简化版本:

long do_sys_open(int dfd, const char __user *filename, int flags, umode_t mode)
{
/* ... irrelevant stuff */
/* allocate the fd, uses a lock */
fd = get_unused_fd_flags(flags);
/* HERE the race condition can arise if another thread calls dup2 on fd */
/* do the real VFS stuff for this fd, also uses a lock */
fd_install(fd, f);
/* ... irrelevant stuff again */
return fd;
}

基本上发生了两件非常重要的事情:分配了一个文件描述符,然后它才真正被 VFS 打开。这两个操作修改了进程的fdt。他们都使用锁,所以在这两个调用中没有什么不好的。

为了记住哪些fds 被分配了一个名为open_fds 的位 vector 被fdt 使用。在 get_unused_fd_flags() 之后,fd 已经分配,​​并且在 open_fds 中设置了相应的位。 fdt 上的锁已被释放,但真正的 VFS 工作尚未完成。

此时,另一个线程(或共享 fdt 情况下的另一个进程)可以调用 dup2,因为锁已被释放而不会阻塞。如果 dup2 在此处采用其正常路径,则 fd 将被替换,但 fd_install 仍将为旧文件运行。因此检查并返回 Ebusy

我在 fd_install() 的评论中找到了关于此竞争条件的更多信息,这证实了我的解释:

/* The VFS is full of places where we drop the files lock between
* setting the open_fds bitmap and installing the file in the file
* array. At any such point, we are vulnerable to a dup2() race
* installing a file in the array before us. We need to detect this and
* fput() the struct file we are about to overwrite in this case.
*
* It should never happen - if we allow dup2() do it, _really_ bad things
* will follow. */

关于c - 使用 dup2 时的竞争条件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23440216/

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