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

时间:2011-09-11 19:57:10

标签: c linux futex

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

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

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

FUTEX_WAIT

让它运行一段时间,最终应该以{{1​​}}(#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返回时线程仍然存在时才有可能。

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

1 个答案:

答案 0 :(得分:0)

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

具体来说,CLONE_VFORK选项的存在似乎意味着这是一个危险的场景。您可能需要一种双向信号机制,以便孩子向父母发出信号,表明其已经足够远,以至于等待孩子是安全的。