我遇到了 Linuxfutex
系统调用(FUTEX_WAIT
操作)的问题,有时似乎无缘无故地提前返回。文档指定了可能导致它提前返回(没有 a FUTEX_WAKE
)的某些条件,但这些都涉及非零返回值:EAGAIN
如果 futex 地址处的值不匹配,则ETIMEDOUT
for timed 等待超时,EINTR
当被 a (非重新启动)信号等。但我看到返回值为 0。除了指针指向 futexFUTEX_WAKE
的线程的终止或终止之外,还有什么可能导致返回值为 0 的返回?set_tid_address
FUTEX_WAIT
如果它有用,我正在等待的特定 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
回来后很好。