關於SIGPIPE訊號

2021-06-18 00:07:13 字數 2926 閱讀 6371

我寫了乙個伺服器程式,在linux下測試,然後用c++寫了客戶端用千萬級別數量的短鏈結進行壓力測試.  但是伺服器總是莫名退出,沒有core檔案.

最後問題確定為, 對乙個對端已經關閉的socket呼叫兩次write, 第二次將會生成sigpipe訊號, 該訊號預設結束程序.

具體的分析可以結合tcp的"四次握手"關閉. tcp是全雙工的通道, 可以看作兩條單工通道, tcp連線兩端的兩個端點各負責一條. 當對端呼叫close時, 雖然本意是關閉整個兩條通道, 但本端只是收到fin包. 按照tcp協議的語義, 表示對端只是關閉了其所負責的那一條單工通道, 仍然可以繼續接收資料. 也就是說, 因為tcp協議的限制, 乙個端點無法獲知對端的socket是呼叫了close還是shutdown.

對乙個已經收到fin包的socket呼叫read方法, 如果接收緩衝已空, 則返回0, 這就是常說的表示連線關閉. 但第一次對其呼叫write方法時, 如果傳送緩衝沒問題, 會返回正確寫入(傳送). 但傳送的報文會導致對端傳送rst報文, 因為對端的socket已經呼叫了close, 完全關閉, 既不傳送, 也不接收資料. 所以, 第二次呼叫write方法(假設在收到rst之後), 會生成sigpipe訊號, 導致程序退出.

為了避免程序退出, 可以捕獲sigpipe訊號, 或者忽略它, 給它設定sig_ign訊號處理函式:

signal(sigpipe,sig_ign);

這樣, 第二次呼叫write方法時, 會返回-1, 同時errno置為sigpipe. 程式便能知道對端已經關閉.

linux下寫socket的程式的時候,如果嘗試send到乙個disconnected socket上,就會讓底層丟擲乙個sigpipe訊號。

這個訊號的預設處理方法是退出程序,大多數時候這都不是我們期望的。因此我們需要過載這個訊號的處理方法。呼叫以下**,即可安全的遮蔽sigpipe

signal (sigpipe, sig_ign);

我的程式產生這個訊號的原因是: 

client端通過 pipe 傳送資訊到server端後,就關閉client端, 這時server端,返回資訊給 client 端時就產生broken pipe 訊號了,伺服器就會被系統結束了。

對於產生訊號,我們可以在產生訊號前利用方法signal(int signum, sighandler_t handler) 設定訊號的處理。如果沒有呼叫此方法,系統就會呼叫預設處理方法:中止程式,顯示提示資訊(就是我們經常遇到的問題)。我們可以呼叫系統的處理方法,也可以自定義處理方法。 

系統裡邊定義了三種處理方法: 

(1)sig_dfl訊號專用的預設動作:

(a)如果預設動作是暫停執行緒,則該執行緒的執行被暫時掛起。當執行緒暫停期間,傳送給執行緒的任何附加訊號都不交付,直到該執行緒開始執行,但是sigkill除外。

(b)把掛起訊號的訊號動作設定成sig_dfl,且其預設動作是忽略訊號 (sigchld)。

(2)sig_ign忽略訊號

(a)該訊號的交付對執行緒沒有影響

(b)系統不允許把sigkill或sigtop訊號的動作設定為sig_dfl

3)sig_err 

專案中我呼叫了signal(sigpipe,sig_ign), 這樣產生sigpipe訊號時就不會中止程式,直接把這個訊號忽略掉。

如果不是正常退出的那就是有訊號引起的程式退出.有些訊號確實能引起程式退出但不生成core;

sighup   終止程序   終端線路結束通話

sigint   終止程序   中斷程序

sigquit   建立core檔案終止程序,並且生成core檔案

sigill   建立core檔案   非法指令

sigtrap   建立core檔案   跟蹤自陷

sigbus   建立core檔案   匯流排錯誤

sigsegv   建立core檔案   段非法錯誤

sigfpe   建立core檔案   浮點異常

sigiot   建立core檔案   執行i/o自陷

sigkill   終止程序   殺死程序

sigpipe   終止程序   向乙個沒有讀程序的管道寫資料

sigalarm   終止程序   計時器到時

sigterm   終止程序   軟體終止訊號

sigstop   停止程序   非終端來的停止訊號

sigtstp   停止程序   終端來的停止訊號

sigcont   忽略訊號   繼續執行乙個停止的程序

sigurg   忽略訊號   i/o緊急訊號

sigio   忽略訊號   描述符上可以進行i/o

sigchld   忽略訊號   當子程序停止或退出時通知父程序

sigttou   停止程序   後台程序寫終端

sigttin   停止程序   後台程序讀終端

sigxgpu   終止程序   cpu時限超時

sigxfsz   終止程序   檔案長度過長

sigwinch   忽略訊號   視窗大小發生變化

sigprof   終止程序   統計分布圖用計時器到時

sigusr1   終止程序   使用者定義訊號1

sigusr2   終止程序   使用者定義訊號2

sigvtalrm   終止程序   虛擬計時器到

關於SIGPIPE訊號

我寫了乙個伺服器程式,在linux下測試,然後用c 寫了客戶端用千萬級別數量的短鏈結進行壓力測試.但是伺服器總是莫名退出,沒有core檔案.最後問題確定為,對乙個對端已經關閉的socket呼叫兩次write,第二次將會生成sigpipe訊號,該訊號預設結束程序.具體的分析可以結合tcp的 四次握手 ...

關於SIGPIPE訊號

我寫了乙個伺服器程式,在linux下測試,然後用c 寫了客戶端用千萬級別數量的短鏈結進行壓力測試.但是伺服器總是莫名退出,沒有core檔案.最後問題確定為,對乙個對端已經關閉的socket呼叫兩次write,第二次將會生成sigpipe訊號,該訊號預設結束程序.具體的分析可以結合tcp的 四次揮手 ...

關於SIGPIPE訊號

我寫了乙個伺服器程式,在linux下測試,然後用c 寫了客戶端用千萬級別數量的短鏈結進行壓力測試.但是伺服器總是莫名退出,沒有core檔案.最後問題確定為,對乙個對端已經關閉的socket呼叫兩次write,第二次將會生成sigpipe訊號,該訊號預設結束程序.具體的分析可以結合tcp的 四次握手 ...