gpt4 book ai didi

c - Linux futex 系统调用虚假唤醒,返回值为 0?

转载 作者:IT王子 更新时间:2023-10-29 01:00:04 30 4
gpt4 key购买 nike

我遇到了 Linux futex 系统调用(FUTEX_WAIT 操作)有时似乎无故提前返回的问题。文档指定了某些可能导致它提前返回的条件(没有 FUTEX_WAKE),但这些都涉及非零返回值:EAGAIN 如果 futex 地址处的值确实如此不匹配,ETIMEDOUT 用于超时等待,EINTR 当被(非重启)信号中断时,等等。但是我看到返回值为 0。什么,除了 FUTEX_WAKEset_tid_address 指针指向 futex 的线程终止,可能导致 FUTEX_WAIT 以返回值 0 返回?

万一它有用,我正在等待的特定 futex 是线程 tid 地址(由 clone 系统调用使用 CLONE_CHILD_CLEARTID 设置),线程有 终止。我(显然不正确)假设 FUTEX_WAIT 操作返回 0 只会在线程终止导致程序逻辑出现严重错误时发生,我已经通过循环和重试修复了这个错误,即使它返回 0,但现在我很好奇为什么会这样。

这是一个最小的测试用例:

#define _GNU_SOURCE
#include <sched.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <linux/futex.h>
#include <signal.h>

static char stack[32768];
static int tid;

static int foo(void *p)
{
syscall(SYS_getpid);
syscall(SYS_getpid);
syscall(SYS_exit, 0);
}

int main()
{
int pid = getpid();
for (;;) {
int x = clone(foo, stack+sizeof stack,
CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND
|CLONE_THREAD|CLONE_SYSVSEM //|CLONE_SETTLS
|CLONE_PARENT_SETTID|CLONE_CHILD_CLEARTID
|CLONE_DETACHED,
0, &tid, 0, &tid);
syscall(SYS_futex, &tid, FUTEX_WAIT, x, 0);
/* Should fail... */
syscall(SYS_tgkill, pid, tid, SIGKILL);
}
}

让它运行一段时间,它最终应该以 Killed (SIGKILL) 终止,这只有在 FUTEX_WAIT 时线程仍然存在的情况下才有可能 返回。

在任何人假设这只是内核在 futex 完成销毁线程之前唤醒它之前(这实际上可能发生在我这里的最小测试用例中),请注意在我的原始代码中,我实际上观察到用户空间代码正在运行在 FUTEX_WAIT 返回后的线程中。

最佳答案

您是否正在处理父操作或子操作先完成之间的竞争条件?您可以通过在 foo() 的开头或在 clone() 之后立即进行小休眠来研究这一理论,以确定事件的强制排序是否掩盖了该问题。我不建议以这种方式修复任何东西,但它可能有助于调查。也许 futex 在子进程进一步完成初始化之前还没有准备好等待,但是父进程的克隆有足够的时间返回给调用者?

具体来说,CLONE_VFORK 选项的存在似乎暗示这是一个危险的场景。您可能需要一种双向信号机制,以便子级向父级发出信号,表明它已经走得足够远,可以安全地等待子级了。

关于c - Linux futex 系统调用虚假唤醒,返回值为 0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7380834/

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