2016-01-21 252 views
0

我試圖更好地理解信號量和所有爵士樂,並且我正在編程使用共享內存和信號量進行通信的服務器和客戶端。它工作得很好,一切都很順利,但我不確定我是否理解信號處理在這種情況下如何正常工作。這是我的服務器的一些示例代碼。我意識到這可能是一個有點多餘同時檢查,但我還挺想了解怪異的行爲我遇到:C:信號處理和信號燈

sig_atomic_t running = 1; 

while(running == 1) { 
    if (sem_wait(server) == -1) { 
     //exit and print error A 
    } 
    if(running == 0) { 
     //exit and print error B 
    } 
    /* do server stuff */ 

    if (sem_post(client) == -1) { 
     //exit and print error 
    } 
} 

服務器是服務器旗號,客戶端是客戶端旗號(其沒有按在這種情況下真的很重要)。運行(這實際上是全球性)是我在信號處理程序使用的變量:

static void init_signalhandler() { 
    struct sigaction sa; 
    sa.sa_handler = terminate; 

    if(sigemptyset(&(sa.sa_mask)) == -1) { 
     bail_out(EXIT_FAILURE, "sigemptyset error"); 
    } 

    if(sigaction(SIGINT, &sa, NULL) == -1) { 
     bail_out(EXIT_FAILURE, "sigaction1 error"); 
    } 

    if(sigaction(SIGTERM, &sa, NULL) == -1) { 
     bail_out(EXIT_FAILURE, "sigaction2 error"); 
    } 
} 

static void terminate(int e) { 
    running = 0; 
    sem_post(server); 
} 

凡bail_out是一個自定義錯誤打印/退出功能。

基本上不管我做什麼,每當我啓動服務器,它就會到達sem_wait(server)部分。如果我試圖通過發送SIGINT來殺死它,有時它會打印出錯誤A,並且有時會打印錯誤B.這看起來完全是隨機的。它有點迫使我使用運行變量,因爲有時候,信號量會通過,而在其他時候,它不會。

回答

0

由於您沒有處理來自sem_wait(3)EINTR,因此其行爲與其應該完全相同。

例如,您在sem_wait(server)處等待。你得到SIGINT並正確處理它。您的sem_wait函數將返回-1,您將退出。 你應該做的,而不是:

if (sem_wait(s_server) == -1) { 
     if(errno == EINTR) continue; 
     bail_out(EXIT_FAILURE, "sem_wait(3) failed"); 
    } 

這將發現錯誤,由於信號在sem_wait程序,你可以終止你的服務器正常,你跳到循環的開始,請參閱運行設置爲0,跳過循環。

有關可以處理哪些錯誤的更多詳細信息,請參見手冊頁sem_wait(3),「返回值」。

+0

但爲什麼然後它有時打印「B」? –