2011-09-11 25 views
5

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.

+0

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

+0

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ụ. –

+0

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 **. –

Trả lời

0

Bạn có thể giải quyết tình trạng cuộc đua giữa việc hoạt động của phụ huynh hoặc con hoàn thành trước không? Bạn có thể nghiên cứu lý thuyết này bằng cách đặt các giấc ngủ nhỏ vào đầu foo() của bạn hoặc ngay sau bản sao() để xác định xem một chuỗi các sự kiện có buộc phải che giấu vấn đề hay không. Tôi không khuyên bạn nên sửa chữa bất cứ điều gì theo cách đó, nhưng nó có thể hữu ích để điều tra. Có lẽ futex chưa sẵn sàng chờ đợi cho đến khi đứa trẻ được tiếp tục thông qua quá trình khởi tạo, nhưng bản sao của bố mẹ có đủ để quay lại người gọi?

Cụ thể, sự hiện diện của tùy chọn CLONE_VFORK dường như ngụ ý đây là một tình huống nguy hiểm. Bạn có thể cần một cơ chế báo hiệu hai chiều để trẻ em báo hiệu cho phụ huynh biết rằng nó đã đủ xa đến mức an toàn để chờ đứa trẻ.

+0

Nếu 'tid' chưa được ghi với giá trị tid tại thời điểm' FUTEX_WAIT' được gọi, thao tác sẽ trả về bằng 'EAGAIN' thay vì 0 (Dù sao, toàn bộ điểm của cờ 'CLONE_PARENT_SETTID' thành' clone' là đảm bảo rằng giá trị đã được viết trước khi một luồng có thể thực thi.) Tôi không thấy bất kỳ khả năng nào cho một chủng tộc ở đây trong không gian người dùng vì không có gì thú vị đang xảy ra trong không gian người dùng ... –

Các vấn đề liên quan