2011-12-13 28 views
13

Người ta nói rằng bạn chỉ nên gọi các chức năng không đồng bộ an toàn bên trong bộ xử lý tín hiệu. Câu hỏi của tôi là gì, những gì cấu thành an toàn không đồng bộ? Một chức năng vừa là reentrantchủ đề an toànkhông đồng bộ an toàn Tôi đoán? Hay không?Điều gì cấu thành sự an toàn không đồng bộ

+0

Tìm thấy [this] (https://www.securecoding.cert.org/confluence/display/seccode/BB.+Definitions). Vì vậy, có vẻ như chức năng có thể không sử dụng các biến toàn cầu (bên cạnh các loại nguyên tử) và làm gián đoạn nó ở bất kỳ điểm nào nên rời khỏi quá trình trong trạng thái nhất quán. – elmo

Trả lời

12

Tái nhập cảnh và an toàn chỉ có một chút hoặc không có gì để thực hiện việc này. Các tác dụng phụ, trạng thái và gián đoạn của các chức năng đó là các sự kiện quan trọng.

asynchronous-safe function [GNU PTH]

Một chức năng là không đồng bộ an toàn, hoặc an toàn không đồng bộ tín hiệu, nếu nó có thể được gọi một cách an toàn và không có tác dụng phụ từ bên trong một bối cảnh xử lý tín hiệu. Tức là, nó phải là có thể bị gián đoạn tại bất kỳ thời điểm nào để chạy tuyến tính ngoài chuỗi mà không gây ra trạng thái không nhất quán. Nó cũng phải hoạt động đúng cách khi dữ liệu toàn cục có thể ở trạng thái không nhất quán. Một số hoạt động không đồng bộ an toàn được liệt kê ở đây:

  • gọi các signal() chức năng để cài đặt lại một handler tín hiệu
  • vô điều kiện sửa đổi một biến volatile sig_atomic_t (như sửa đổi để loại này là nguyên tử)
  • gọi các _Exit() chức năng đến ngay lập tức chấm dứt thực hiện chương trình
  • gọi hàm an toàn không đồng bộ , như được chỉ định bởi triển khai của bạn

Một số chức năng là an toàn không đồng bộ một cách an toàn. Nếu một hàm thực hiện bất kỳ hoạt động nào khác của , nó có thể không an toàn không đồng bộ.

Quy tắc chung là điều này - chỉ báo hiệu một số biến điều kiện từ trình xử lý tín hiệu (chẳng hạn như điều kiện futex/pthread, wake up epoll loop, v.v.).

UPDATE:

Như EmployedRussian đề nghị, thậm chí kêu gọi pthread_cond_signal là một ý tưởng tồi. Tôi đã kiểm tra mã nguồn của eglibc gần đây và nó có cặp khóa/mở khóa trong đó. Vì vậy, giới thiệu một khả năng cho một bế tắc. Điều này khiến chúng tôi có một vài tùy chọn để báo hiệu các chủ đề khác:

  1. Sử dụng eventfd.
  2. Thay đổi biến nguyên tử toàn cầu và hy vọng SA_RESTART không được đặt và các chủ đề khác sẽ kiểm tra nguyên tử của chúng tôi.
+5

Có một danh sách lớn hơn nhiều chức năng được [bảo đảm an toàn-tín hiệu-an toàn bởi POSIX.1-2008] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04_03) (bạn sẽ phải cuộn xuống một chút cho danh sách), bao gồm phần lớn các cuộc gọi hệ thống "Unix" truyền thống và truy cập vào 'errno'. Ngoài ra, nếu bạn biết rằng trình xử lý tín hiệu của bạn sẽ chỉ được gọi khi thực thi bình thường bị chặn trên ['sigsuspend'] (http://pubs.opengroup.org/onlinepubs/9699919799/functions/sigsuspend.html), thì sẽ an toàn làm công cụ tùy ý trong trình xử lý. – zwol

+1

Không có chức năng 'pthread_ *' nào là an toàn-tín hiệu an toàn, do đó, "biến điều kiện tín hiệu pthread" là một lời khuyên xấu (TM). –

+0

@EmployedRussian: Không phải là nó không an toàn, nó có thể không đánh thức ai đó chờ đợi trên một biến điều kiện POSIX. –

1

Đối với mã của riêng bạn, có, tái nhập và đảm bảo an toàn là những đặc điểm bạn cần, tùy thuộc vào cách bạn thiết lập cơ chế xử lý tín hiệu của mình, bộ xử lý tín hiệu của bạn có thể bị gián đoạn bởi tín hiệu khác. Nói chung, hãy cố gắng làm càng ít công việc càng tốt bên trong bộ xử lý tín hiệu.Đặt cờ để kích hoạt mã đặc biệt trong luồng chương trình bình thường của bạn có lẽ là tất cả những gì bạn nên làm.

Đối với các chức năng trong hệ điều hành mà bạn có thể gọi, hãy xem man 7 signal để biết danh sách những gì an toàn để gọi. Lưu ý rằng malloc()free()không phải trong danh sách. Các API đồng bộ hóa pthread cũng không nằm trong danh sách, nhưng tôi nghĩ rằng một số sẽ phải an toàn để gọi, vì vậy bạn có thể thiết lập một cờ toàn cục một cách an toàn trong một trình xử lý tín hiệu.

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