2011-12-06 69 views
20

Tôi đã gỡ lỗi chương trình Python phân biệt sau khi nhận được ngoại lệ KeyboardInterrupt. Điều này thường được thực hiện bằng cách nhấn Ctrl + C từ vỏ. Để kiểm tra xem một mã cụ thể có thay đổi được lỗi hay không, tôi đã có một tập lệnh shell nhỏ gửi SIGINT đến chương trình vào thời điểm ngẫu nhiên sau khi khởi động. Vấn đề tôi gặp phải là gửi Ctrl + C dường như có tác dụng khác với chương trình hơn là gửi tín hiệu SIGINT và do đó không gây ra lỗi xuất hiện, vì vậy tôi tự hỏi sự khác biệt giữa hai hành động là gì.Sự khác nhau giữa Ctrl-C và SIGINT là gì?

Chương trình không bắt bất kỳ thao tác bàn phím nào cả, và chỉ là chương trình python với một số luồng/quy trình trong đó. Nó cài đặt không có trình xử lý tín hiệu (mặc dù Python làm), và stty -a cho intr = ^C. Tôi nghi ngờ rằng có thể là Ctrl + C gửi SIGINT cho tất cả các quy trình con/luồng trong khi kill -INT chỉ gửi đến quy trình chính, nhưng đó là điều mà tôi nghi ngờ.

Đây là tập lệnh shell gửi số kill -INT.

wait 
while :; do 
    seconds="$(python -c 'import random; print random.random()*4')" 
    ./mandos --debug --configdir=confdir \ 
      --statedir=statedir --no-restore --no-dbus & 
    pid=$! 
    { sleep $seconds; kill -INT $pid; } & 
    fg %./mandos 
    status=$? 
    if [ $status -gt 1 ]; then 
     echo "Failed exit $status after $seconds seconds" 
     break 
    fi 
    wait 
done 
+0

Tôi không chắc chắn về sự khác biệt này, nhưng ctrl + c có thể gửi 'SIGTERM' thay vì' SIGINT'. Ngoài ra, khi xử lý các trường hợp ngoại lệ là bạn làm sạch các tiểu trình/chủ đề của bạn một cách chính xác? Cách python xử lý chủ đề Tôi không tin rằng nó sẽ seg-fault, nhưng nó có thể có thể với các tiểu quy trình. – David

+0

+ C có thể được định cấu hình, vì vậy hãy kiểm tra cài đặt 'stty -a' của bạn, tìm' intr =^C', có thể^C cũng được đặt cho cái gì khác? – cdarke

+0

có bất kỳ đa luồng nào trong mã không? – Casey

Trả lời

11

^C gửi SIGINT cho tất cả các quy trình trong nhóm tiến trình nền trước. Để thực hiện điều tương đương với kill, bạn nên gửi tín hiệu vào nhóm quá trình (hệ điều hành cấp khái niệm):

kill -SIGINT -<pid> 

hoặc công việc (vỏ cấp khái niệm, các đường ống dẫn đã kết thúc với &):

kill -SIGINT % 
+0

Đây là những gì tôi đang tìm kiếm, nhưng không rõ lý do mã vẫn không segfault khi tôi sử dụng kịch bản tự động. Tôi tìm thấy lỗi gây ra python để sụp đổ - python thư viện đa được thực hiện với chủ đề, và nó gây ra segfaults trong gobject nếu một trong những không gọi gobject.threads_init. Tuy nhiên, câu hỏi ban đầu cho tôi là trái như một bí ẩn là tại sao ctrl + c được gọi thủ công đã kích hoạt lỗi, nhưng kịch bản tự động thì không. – Belorn

+2

Xin lỗi vì đã bị lừa đảo, nhưng '%' có ý nghĩa gì trong ngữ cảnh này? –

+1

@KevinCantwell: nó đề cập đến công việc hiện tại, tức là công việc nền cuối cùng (hoặc bắt đầu ở chế độ nền, hoặc dừng lại trong khi nó ở nền trước và do đó được tạo nền). – ninjalj

4

Như described here:

Python cài đặt một số lượng nhỏ các bộ xử lý tín hiệu theo mặc định: SIGPIPE bị lờ đi (để ghi lỗi trên đường ống và ổ cắm có thể được báo cáo là ngoại lệ Python bình thường) và SIGINT được dịch sang Ngoại lệ tắt bàn phím. Tất cả những điều này có thể bị ghi đè.

như vậy, hành vi nên giống nhau giữa gửi tin SIGINT và Ctrl +c.

Tuy nhiên, bạn phải cẩn thận với KeyboardInterrupt, nếu ở đâu đó trong mã của bạn, bạn đã có một

try: 
    ... 
except: # notice the lack of exception class 
    pass 

này sẽ "ăn" biệt lệ KeyboardInterrupt.

+0

Cảm ơn lời khuyên. tìm thấy một dòng làm điều đó, và tôi nghĩ rằng sẽ sửa chữa một lỗi không liên quan. Nhưng ngay cả với những nhận xét ra, vấn đề chính với segfault vẫn còn đó, và một trong những kỳ lạ hơn mà gửi kill -INT không kích hoạt nó nhưng ctrl + c không. – Belorn

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