2011-12-12 44 views
8

GDB cho tôi biết rằng pthread_kill đang gây ra lỗi phân đoạn trong chương trình của tôi. Về cơ bản, tôi đang sử dụng pthread_kill để kiểm tra xem luồng có còn hay không được cấp ID.Lỗi phân đoạn gây ra bởi pthread_kill

Tôi đã tìm kiếm trên web và thấy rằng có thể là pthread_kill đang gây ra lỗi phân đoạn khi TID không hợp lệ. Có, tôi đã thử nghiệm chương trình của mình bằng cách sử dụng "không hợp lệ" (do tôi) TID thuộc loại int. Đó có thể là nguyên nhân thực sự?

+0

Bạn đang sử dụng những giá trị "không hợp lệ" nào? –

+0

@DanFego Ví dụ: 1001 –

+0

Vì pthread_t là một loại mờ, sử dụng số nguyên (như 1001) về lý thuyết có thể gây ra sự cố và sự cố tiếp theo. Bạn có nhận được bất kỳ cảnh báo nào khi biên dịch với -Wall không? –

Trả lời

14

pthread_t không phải là ID chủ đề hoặc chỉ mục số. Nó là một loại đục. Tạo nên các giá trị có thể dẫn đến sự cố.

Trên Linux NPTL, pthread_t được sử dụng như một con trỏ:

int 
__pthread_kill (threadid, signo) 
    pthread_t threadid; 
    int signo; 
{ 
    struct pthread *pd = (struct pthread *) threadid; 

Nó nên được khá rõ ràng nơi mà mọi thứ đang đi sai đã :) Lưu ý rằng pointerness này cũng là một chi tiết thực hiện - thi Linuxthreads cũ sử dụng các chỉ số dạng số vào một bảng và ở đó bạn thực sự có thể tạo ra các TID và không mong đợi mọi thứ bị lỗi.

Bạn cần phải tự theo dõi cuộc sống của luồng và chết. A pthread_t có hiệu lực cho đến khi bạn gọi thành công pthread_join. Nếu bạn muốn kiểm tra xem hợp lệpthread_t có còn hoạt động hay không, hãy gọi pthread_tryjoin_np trên đó; nếu nó trả về EBUSY, luồng vẫn còn hoạt động. Nếu hàm thành công, số pthread_t không còn hợp lệ; bạn không được tái sử dụng nó vào thời điểm này - vì vậy bạn phải ghi chú ở đâu đó rằng chuỗi đó đã chết và không cần kiểm tra nữa!

Bạn có thể, tất nhiên, triển khai hệ thống theo dõi của riêng bạn - tạo bảng ở đâu đó của liveness, một hệ thống để phân phát các TID và chuyển chúng vào các chủ đề mới được tạo. Yêu cầu mỗi chuỗi đánh dấu chính nó là đã chết trước khi thoát (có thể sử dụng pthread_cleanup_push để bạn xử lý việc hủy chuỗi và pthread_exit) và tách chủ đề sao cho bạn không cần tham gia nó (sử dụng pthread_detach). Bây giờ bạn đã kiểm soát rõ ràng báo cáo chuỗi chết của bạn.

+1

Trang hướng dẫn cho [pthread_kill] (https://www.kernel.org/doc/man-pages /online/pages/man3/pthread_kill.3.html) nói rằng bạn có thể sử dụng 'pthread_kill (t, 0)' để 'kiểm tra sự tồn tại của t', có nghĩa là có thể thực hiện cuộc gọi với các giá trị pthread_t không hợp lệ. trang không chính xác? – Brandon

+1

@Brandon xem http://sourceware.org/bugzilla/show_bug.cgi?id=4509 và http://udrepper.livejournal.com/16844.html.dreppers đối số sems khá trí tuệ lười biếng, nhưng nó sẽ xuất hiện rằng không có ý định hỗ trợ pthread_kill trên TIDs không hợp lệ trong glibc, do đó, cách tiếp cận của việc sử dụng pthread_kill để kiểm tra sự tồn tại của thread là không làm việc –

+0

@JoshuaClayton cảm ơn cho các liên kết. – Brandon

1

Để khắc phục hạn chế này trong mã của tôi, tôi đặt TID bằng không khi mã không chạy

memset(&thread, '\0', sizeof(pthread_t)); 

... và kiểm tra xem nó for null trước khi gọi pthread_kill

//this code will run if thread is not valid 
if (!thread || ESRCH == pthread_kill(thread, 0)) { 
    //do stuff and create the thread 
}