2013-07-10 43 views
6

Tôi có một quy trình máy chủ đa luồng, được viết bằng C/C++ mà tôi đang cố gắng cấu hình với các công cụ theo dõi của Google. Tuy nhiên khi tôi chạy quá trình với perftools, khá sớm máy chủ của tôi dừng lại với một lỗi "syscall interrupted", mà tôi nghĩ là do SIGPROF gây ra. (Cuộc gọi hệ thống thực sự đang bị gián đoạn nằm sâu bên trong cuộc gọi của tôi tới zmq_recv, nhưng tôi không nghĩ nó thực sự quan trọng như thế nào.)SIGPROF giết chết máy chủ của tôi khi sử dụng google perftools

Hành vi này có được mong đợi không? Tôi có nên xử lý rõ ràng trường hợp này bằng cách nào đó không? Hay có gì sai ở đây?

Trả lời

8

Từ các tài liệu zeroMQ cho zmq_recv() chúng ta có thể mong đợi nó để trở EINTR nếu một tín hiệu nhận được khi nó được tiến hành.

Tạo tín hiệu ngay giữa cuộc gọi zmq_recv() sẽ là một nhiệm vụ khó khăn đối với mọi thử nghiệm. May mắn là gperftools tạo ra một tấn SIGPROF s đã phát hiện ra "lỗi" tinh tế này trong mã của bạn.

này phải được xử lý một cách duyên dáng trong đang của bạn như là khuôn khổ zeroMQ được một cách duyên dáng nhượng kiểm soát. Logic retry có thể đơn giản như thay đổi các cuộc gọi hiện tại:

/* Block until a message is available to be received from socket */ 
    rc = zmq_recv (socket, &part, 0); 

với cái mới (với thử lại logic) như sau:

/* Block until a message is available to be received from socket 
    * Keep retrying if interrupted by any signal 
    */ 
    rc = 0; 
    while(rc != EINTR) { 
     rc = zmq_recv (socket, &part, 0); 
    } 

Cũng install a signal handler function trong chương trình của bạn. Người ta có thể đơn giản bỏ qua sự gián đoạn do SIGPROF và tiếp tục thử lại.

Cuối cùng, bạn có thể muốn xử lý các tín hiệu cụ thể và hành động tương ứng. Ví dụ: chấm dứt chương trình của bạn một cách duyên dáng ngay cả khi người dùng nhấn CTRL + C trong khi chương trình của bạn đang chờ trên zmq_recv().

/* Block until a message is available to be received from socket 
    * If interrupted by any signal, 
    * - in handler-code: Check for signal number and update status accordingly. 
    * - in regular-code: Check for status and retry/exit as appropriate 
    */ 
    rc = 0; 
    while(rc != EINTR && status == RETRY) { 
     rc = zmq_recv (socket, &part, 0); 
    } 

Vì lợi ích của việc giữ mã "sạch", bạn sẽ được phục vụ tốt hơn bằng cách sử dụng đoạn mã trên để viết riêng static inline chức năng bao bọc của bạn xung quanh zmq_recv() mà bạn có thể gọi trong chương trình của bạn.

Về quyết định để làm cho zmq_recv() trở EINTR khi nhận được tín hiệu, bạn có thể muốn kiểm bài viết này nói về các worse is better philosophy đằng sau một thiết kế như vậy là đơn giản từ một điểm-of-view thực hiện.


CẬP NHẬT: Mã dự liệu để xử lý tín hiệu trong bối cảnh zmq_recv() có sẵn tại git.lucina.net/zeromq-examples.git/tree/zmq-camera.c. Nó nằm dọc theo các dòng giống như đã giải thích ở trên, nhưng nó được kiểm tra tốt và sẵn sàng để sử dụng với các chú thích chi tiết một cách ân cần rắc khắp mọi nơi (yayyy zeromq!).