2009-04-29 38 views
7

Có cách nào để nhúng python, cho phép gọi lại từ python đến C++, cho phép mã Pythhon sinh ra luồng và tránh deadlocks không?Python nhúng với chủ đề - tránh deadlocks?

Vấn đề là thế này:

  • Để gọi vào Python, tôi cần phải giữ GIL. Thông thường, tôi làm điều này bằng cách nhận trạng thái luồng chính khi lần đầu tiên tôi tạo trình thông dịch và sau đó sử dụng PyEval_RestoreThread() để lấy GIL và hoán đổi trạng thái luồng trước khi tôi gọi vào Python.

  • Khi được gọi từ Python, tôi có thể cần truy cập một số tài nguyên được bảo vệ được bảo vệ bởi một phần quan trọng riêng trong máy chủ của tôi. Điều này có nghĩa rằng Python sẽ giữ GIL (có khả năng từ một số thread khác so với ban đầu tôi được gọi vào), và sau đó cố gắng để có được khóa bảo vệ của tôi.

  • Khi gọi vào Python, tôi có thể cần phải giữ cùng một khóa, vì tôi có thể đang lặp qua một số tập hợp các đối tượng, ví dụ.

Vấn đề là ngay cả khi tôi giữ GIL khi tôi gọi vào Python, Python có thể từ bỏ nó, đưa nó vào một chủ đề khác, và sau đó gọi chủ đề đó vào máy chủ của bạn, khóa. Trong khi đó, máy chủ có thể lấy ổ khóa máy chủ, và khóa GIL, và gọi vào Python. Deadlock xảy ra sau đó.

Vấn đề ở đây là Python từ bỏ GIL sang một luồng khác trong khi tôi đã gọi nó. Đó là những gì nó dự kiến ​​sẽ làm, nhưng nó làm cho nó không thể tuần tự khóa - ngay cả khi tôi lần đầu tiên lấy GIL, sau đó lấy khóa của riêng tôi, sau đó gọi Python, Python sẽ gọi vào hệ thống của tôi từ sợi khác, mong muốn có khóa riêng của tôi (bởi vì nó không giải trình tự GIL bằng cách phát hành nó). Tôi không thể làm cho phần còn lại của hệ thống sử dụng GIL cho tất cả các khóa có thể có trong hệ thống - và điều đó thậm chí sẽ không hoạt động đúng, bởi vì Python vẫn có thể giải phóng nó tới một luồng khác.

Tôi thực sự không thể đảm bảo rằng máy chủ lưu trữ của tôi không giữ bất kỳ khóa nào khi nhập Python, vì tôi không kiểm soát được tất cả mã trong máy chủ.

Vậy, có phải trường hợp này không thể thực hiện được không?

+0

Bạn có thể yêu cầu mã C + + của bạn để giữ GIL trước khi nó mua lại ổ khóa máy chủ không? – Dave

Trả lời

2

"Khi gọi vào Python, tôi có thể cần phải giữ cùng một khóa, vì tôi có thể đang lặp qua một số tập hợp các đối tượng, ví dụ."

Điều này thường chỉ ra rằng một quy trình đơn lẻ có nhiều luồng không phù hợp. Có lẽ đây là một tình huống mà nhiều quy trình - mỗi quy trình với một đối tượng cụ thể từ bộ sưu tập - có ý nghĩa hơn.

Quy trình độc lập - mỗi quy trình có nhóm chủ đề riêng của họ - có thể dễ quản lý hơn.

+0

Một quy trình duy nhất là chính xác những gì tôi cần (quy trình được đề cập thực sự là một trình duyệt web plug-in). Do đó, thật không may, đề xuất của bạn không trả lời hoặc áp dụng cho câu hỏi của tôi. –

+1

Vui lòng cập nhật câu hỏi của bạn với các thông tin bổ sung - không thêm thông tin trong nhận xét. "Trình duyệt web plug-in" là thông tin mới và thuộc về câu hỏi. –

2

Mã được gọi là python phải giải phóng GIL trước khi lấy bất kỳ khóa nào của bạn. Bằng cách đó tôi tin rằng nó không thể vào được cái chết.

+0

Câu trả lời hay. Hãy nhớ rằng GIL chỉ tồn tại để bảo vệ cấu trúc dữ liệu nội bộ của trình thông dịch Python. Nếu một chuỗi gọi vào một số mã không phải Python, nó có thể giải phóng GIL một cách an toàn trong khi mã đó thực thi. – mhsmith

-1

Gần đây đã có một số cuộc thảo luận về một vấn đề tương tự trong danh sách pyopenssl. Tôi sợ nếu tôi cố gắng giải thích điều này tôi sẽ làm cho nó sai, vì vậy thay vào đó tôi sẽ giới thiệu bạn đến the problem in question.