2013-07-10 10 views
6

Mam proces serwera wielowątkowego, napisany w C/C++, który próbuję profilować za pomocą narzędzi Google perftools. Jednak po uruchomieniu procesu za pomocą perftools, wkrótce mój serwer zatrzymuje się z błędem "syscall interrupted", który moim zdaniem jest spowodowany przez przychodzące SIGPROF. (Faktyczne wywołanie systemowe, które jest przerywane, jest głęboko w moim wywołaniu do zmq_recv, ale nie sądzę, że to naprawdę ważne, które to jest.)SIGPROF zabija mój serwer podczas używania google perftools

Czy to oczekiwane zachowanie? Czy powinienem w jakiś sposób jawnie obsługiwać tę sprawę? Czy coś tu nie gra?

Odpowiedz

8

Z dokumentacji zeroMQ dla zmq_recv() możemy spodziewać się, że do powrotu EINTR jeśli odbierany jest sygnał, kiedy jest w toku.

Generowanie sygnałów w samym środku rozmowy zmq_recv() byłoby trudnym zadaniem dla każdego testu. Na szczęście gperftools generowanie tony z SIGPROF s odkrył ten subtelny "błąd" w kodzie.

Ten koniecznością być bezpiecznie obchodzić w kodzie jako ramy zeroMQ jest wdzięcznie cesji kontroli. Logika ponawiania może być tak proste, jak modyfikację istniejącego połączenia:

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

z nową (z logiki ponawiania) w następujący sposób:

/* 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); 
    } 

też install a signal handler function w programie. Można po prostu zignorować przerwanie z powodu SIGPROF i kontynuować ponawianie próby.

Na koniec możesz chcieć obsłużyć określone sygnały i odpowiednio postępować. Na przykład, wdzięcznie zakończenia programu, nawet jeśli użytkownik naciśnie Ctrl + C natomiast program czeka na 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); 
    } 

W trosce o utrzymanie kodu „czysty”, będzie lepiej służył stosując powyższy fragment napisać własny static inline funkcji otoki wokół zmq_recv() który można zadzwonić w programie.

Odnośnie decyzji dokonania zmq_recv() powrót EINTR po otrzymaniu sygnałów, może chcesz kasy ten artykuł, który mówi o worse is better philosophy za taki projekt, który jest prostszy od punktu z widzenia realizacji.


UPDATE: Udokumentowane kod obsługi sygnałów w kontekście zmq_recv() dostępne w git.lucina.net/zeromq-examples.git/tree/zmq-camera.c. Jest on zgodny z wytycznymi opisanymi powyżej, ale wygląda dobrze przetestowany i gotowy do użycia ze szczegółowymi komentarzami łaskawie posypanymi po całym (yayyy zeromq!).