2009-11-02 16 views
7

Vì một số lý do, siginterrupt() dường như chỉ thiết lập hành vi cho tín hiệu đầu tiên nhận được.siginterrupt() chỉ hoạt động đối với tín hiệu đầu tiên? (Python)

Trong chương trình ví dụ này, SIGQUIT đầu tiên dường như không làm gì cả, nhưng sigquit thứ hai in "SIGQUIT Handler" và s.accept() ném một ngoại lệ cuộc gọi hệ thống bị gián đoạn.

from signal import * 
from socket import * 
import sys 

def sigquitHandler(signum, frame): 
     print("SIGQUIT Handler") 

s = socket() 
s.bind(("0.0.0.0", int(sys.argv[1]))) 
s.listen(5) 

signal(SIGQUIT, sigquitHandler) 
siginterrupt(SIGQUIT, False) 

client, addr = s.accept() # Or any syscall that blocks 
client.close() 
s.close() 

Tôi hiểu nhầm điều gì ở đây?


Chỉnh sửa: Đây là điều khác mà tôi không thể tìm ra, trong chương trình này, SIGQUIT ngắt chọn(). Đó có phải là chuyện xảy ra không?

from signal import * 
import select 
import sys 

def sigquitHandler(signum, frame): 
    print("SIGQUIT Handler") 

signal(SIGQUIT, sigquitHandler) 
siginterrupt(SIGQUIT, False) 

select.select([sys.stdin], [], []) 
+1

Tôi nghĩ rằng 'siginterrupt' thực sự chỉ áp dụng cho các cuộc gọi hệ thống có liên quan đến việc chuyển giao dữ liệu (nguyên thủy như mở, đọc hoặc viết). Tôi không nghĩ rằng nó áp dụng cho các cuộc gọi hệ thống như 'select'. – mhawke

+0

Ah, ok. Cảm ơn một lần nữa :) –

Trả lời

2

Bạn đang sử dụng unix nào? Ở mức C, có các cách triển khai và ngữ nghĩa khác nhau để xử lý tín hiệu trên BSD và Hệ thống 5 (SYSV).

Tôi đoán là bạn đang sử dụng SYSV, trong trường hợp này, bố trí tín hiệu được đặt lại về SIG_DFL sau khi xử lý tín hiệu đã trả về (xử lý tín hiệu cổ điển). Trên SYSV, bạn cần gọi signal trong trình xử lý để cài đặt lại trình xử lý đó.

Python nhiều hay ít cung cấp xử lý tín hiệu kiểu BSD. Vì vậy, trên một hệ điều hành SYSV, Python phải quản lý việc cài đặt lại trình xử lý tín hiệu qua signal. Bây giờ, theo doco Python cho siginterrupt:

Lưu ý rằng cài đặt một xử lý tín hiệu với tín hiệu() sẽ thiết lập lại các hành vi restart để ngắt bởi siginterrupt ngầm gọi() với một giá trị cờ đúng đối với được cung cấp tín hiệu .

Và có bạn đi - nếu Python được tự động cài đặt lại xử lý tín hiệu của bạn (để cung cấp BSD như ngữ nghĩa), nó có thể cũng được làm như vậy trong một cách mà mặc nhiên gọi siginterrupt(1).

Tất nhiên, dự đoán của tôi có thể sai.

Bạn thể có thể khắc phục điều này bằng cách định nghĩa sigquitHandler như thế này:

def sigquitHandler(signum, frame): 
    print("SIGQUIT Handler") 
    siginterrupt(SIGQUIT, False) 

Nó phụ thuộc vào khi nào và như thế nào Python được khôi phục lại bố trí tín hiệu.

EDIT

Thêm siginterrupt(SIGQUIT, False) để xử lý tín hiệu đã không có ảnh hưởng.

EDIT 2

Sau khi một số poking hơn xung quanh trong mã nguồn python2.6 nói rõ rằng đây không chỉ là một vấn đề SYSV. Nó cũng sẽ ảnh hưởng đến các hệ thống BSD.

+0

Điều đó có ý nghĩa, cảm ơn! –

4

Đây là số bug của python."siginterrupt with flag = False được đặt lại khi tín hiệu nhận được", đã được sửa trong bản phát hành python2.6 sau này. (2.6.6+, 2.7+)

Đối với câu lệnh thứ hai, ngắt liên kết không ảnh hưởng đến select().

thấy http://lkml.org/lkml/2005/7/23/119

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