我寫了乙個伺服器程式,在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的 四次握手 ...