Tôi đã gặp sự cố với hoạt động syscall Linux futex
(hoạt động FUTEX_WAIT
) đôi khi trở lại sớm dường như không có nguyên nhân. Tài liệu chỉ định các điều kiện nhất định có thể khiến nó quay trở lại sớm (không có FUTEX_WAKE
) nhưng tất cả đều liên quan đến giá trị trả về không: EAGAIN
nếu giá trị tại địa chỉ futex không khớp, ETIMEDOUT
cho thời gian chờ đã hết thời gian chờ, EINTR
khi bị gián đoạn bởi một tín hiệu (không khởi động lại), v.v. Nhưng tôi thấy giá trị trả về là 0. Ngoài ra, còn hơn FUTEX_WAKE
hoặc chấm dứt chuỗi có số điểm con trỏ là set_tid_address
, có thể làm cho FUTEX_WAIT
trở về với giá trị trả về 0?Linux futex syscall spurious wakes với giá trị trả về 0?
Trong trường hợp đó là hữu ích, đặc biệt futex Tôi đã chờ đợi trên là địa chỉ chủ đề tid (theo quy định của clone
syscall với CLONE_CHILD_CLEARTID
), và các chủ đề đã không chấm dứt. Giả định của tôi (dường như không chính xác) rằng hoạt động FUTEX_WAIT
trả về 0 chỉ có thể xảy ra khi chuỗi bị chấm dứt dẫn đến lỗi nghiêm trọng trong logic chương trình, mà tôi đã cố định bằng cách lặp lại và thử lại ngay cả khi nó trả về 0, nhưng giờ tôi tò mò tại sao nó lại xảy ra.
Dưới đây là một trường hợp thử nghiệm tối thiểu:
#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);
}
}
Let it chạy một thời gian, nó cuối cùng sẽ chấm dứt với Killed
(SIGKILL
), mà chỉ có thể nếu các chủ đề vẫn còn tồn tại khi FUTEX_WAIT
lợi nhuận.
Trước khi bất kỳ ai giả định đây chỉ là hạt nhân đánh thức futex trước khi nó kết thúc phá hủy luồng (có thể xảy ra trong trường hợp thử nghiệm tối thiểu của tôi ở đây), xin lưu ý rằng trong mã ban đầu của tôi, tôi thực sự đã quan sát mã vùng người dùng chạy trong luồng tốt sau khi trả về FUTEX_WAIT
.
Tôi nghĩ chúng ta có thể cần xem một ví dụ tối thiểu; thật khó để đưa ra lời khuyên đáng kể, vì rất nhiều điều chưa được biết (tôi sẽ đăng một linh cảm của tôi như một câu trả lời tạm thời, bởi vì nó rất lớn để nhận xét) – sehe
Thật vậy, tôi sẽ xem liệu tôi có thể tập hợp tối thiểu không thí dụ. –
hm, tôi nghĩ trang người đàn ông khá rõ ràng. các điều kiện theo giá trị trả về của 'FUTEX_WAIT' đủ điều kiện không phải là điều kiện * lỗi *, không chỉ chẩn đoán. Sau đó, nó nói "Trong trường hợp có lỗi, tất cả các hoạt động trở về -1, và thiết lập errno để chỉ ra lỗi." Mặt khác, các điều kiện ở đây không được lặp lại trong phần ** ERRORS **. –