2010-06-23 20 views
14

Tôi có một trình nền Python bằng ren. Giống như bất kỳ daemon tốt, nó muốn khởi động tất cả các chủ đề công nhân của nó, sau đó chờ đợi cho đến khi nó được yêu cầu chấm dứt. Tín hiệu bình thường cho việc chấm dứt là SIGTERM và trong hầu hết các ngôn ngữ tôi muốn giữ để chấm dứt bằng cách chờ một sự kiện hoặc mutex, do đó, việc sử dụng threading.Event có ý nghĩa với tôi. Vấn đề là đối tượng Event của Python và các tín hiệu Unix dường như không hoạt động tốt với nhau.Tại sao sử dụng kết quả luồng.Event trong SIGTERM không bị bắt?

này làm việc như mong đợi, chấm dứt trên SIGTERM:

import signal 
import time 

RUN = True 

def handle(a, b): 
    global RUN 
    print "handled" 
    RUN = False 

signal.signal(signal.SIGTERM, handle) 
while RUN: 
    time.sleep(0.250) 
print "Stopping" 

nhưng kết quả này trong không SIGTERM được giao (ví dụ, hoàn toàn ngoài bỏ, "xử lý" không bao giờ được in):

import signal 
import threading 

RUN_EVENT = threading.Event() 

def handle(a, b): 
    print "handled" 
    RUN_EVENT.set() 

signal.signal(signal.SIGTERM, handle) 
RUN_EVENT.wait() 
print "Stopping" 

Vì vậy, câu hỏi của tôi là:

  1. Tôi có lạm dụngkhôngtheo một cách nào đó?
  2. Nếu không, có một sự thay thế nào khác với cơ chế bình chọn và ngủ trong ví dụ đầu tiên không?
  3. Ngoài ra nếu tôi không, tại sao sử dụng threading.Event hãy hủy trình xử lý tín hiệu?

Trả lời

13

Từ Python documentation on signals:

Mặc dù bộ xử lý tín hiệu Python được gọi là không đồng bộ như xa như người sử dụng Python là có liên quan, họ chỉ có thể xảy ra giữa các hướng dẫn “nguyên tử” của trình thông dịch Python. Điều này có nghĩa là các tín hiệu đến trong các phép tính dài được thực hiện hoàn toàn trong C (như biểu thức chính quy phù hợp trên các phần lớn văn bản) có thể bị trì hoãn trong một khoảng thời gian tùy ý.

Tôi đã thử nghiệm các lớp khác nhau và không ai trong số chúng hoạt động theo cách bạn muốn - điều này có thể là do cách Python xử lý tín hiệu.

Trong signal, tuy nhiên, có chức năng pause() ngủ cho đến khi nhận được tín hiệu bởi quy trình. Ví dụ sửa đổi của bạn sẽ trông như thế này:

import signal 

RUN = True 

def handle(a, b): 
    global RUN 
    print "handled" 
    RUN = False 

signal.signal(signal.SIGTERM, handle) 
while RUN: 
    signal.pause() 
print "Stopping" 

Tôi đã kiểm tra nó trên Linux, nó hoạt động. Tôi không nghĩ rằng nó phân loại như bình chọn và ngủ nữa nếu ứng dụng của bạn không sử dụng nhiều tín hiệu khác.

+0

Tính năng khó chịu của Python, nhưng là giải pháp hoàn hảo. Cảm ơn bạn. Tôi sẽ thú nhận rằng nó đã không xảy ra với tôi để tìm các hạn chế bổ sung về sử dụng 'tín hiệu', vì tôi biết rằng C tương đương sẽ hoạt động tốt. –

+3

Điều này có nghĩa là cách duy nhất để xử lý các tín hiệu là dành chủ đề chính (phụ huynh) cho các tín hiệu bắt (bằng cách chặn trên 'signal.pause()')? Điều đó ngụ ý là chủ đề chính không thể làm bất cứ điều gì hữu ích nữa. Nói cách khác, bạn không thể có mô hình master/worker (trong đó 2 chủ đề nói chuyện với nhau) nhưng bạn cần mô hình master/worker + worker (nơi 2 nhân viên nói chuyện với nhau và master không làm gì cả. –

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