[英]How to handle EINTR (interrupted System Call)
我的用戶空間應用程序有時會在收到EINTR信號后以某種方式阻塞。
我用strace錄制的內容:
time(NULL) = 1257343042
time(NULL) = 1257343042
rt_sigreturn(0xbff07be4) = -1 EINTR (Interrupted system call)
--- SIGALRM (Alarm clock) @ 0 (0) ---
time(NULL) = 1257343042
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGUSR1 (User defined signal 1) @ 0 (0) ---
sigreturn() = ? (mask now [ALRM])
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGTERM (Terminated) @ 0 (0) ---
time(NULL) = 1257343443
time(NULL) = 1257343443
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2) = ? ERESTARTSYS (To be restarted)
--- SIGWINCH (Window changed) @ 0 (0) ---
futex(0xb7cea80c, 0x80 /* FUTEX_??? */, 2
我可以捕獲EINTR信號嗎?如何重復寫入,讀取或選擇等有關呼叫? 即使我使用第三方庫處理系統調用,如何確定此EINTR發生的位置?
為什么我的應用程序在收到EINTR后被完全阻止(參見strace轉儲:我發送了一個通常應該處理的SIGUSR1)? 為什么futex()將ERESTARTSYS返回給用戶空間?
謝謝
調用write(或其他阻塞操作)的代碼必須知道EINTR。 如果在阻塞操作期間發生信號,則操作將(a)返回部分完成,或(b)返回失敗,什么都不做,並將errno設置為EINTR。
因此,對於在中斷后重試的全失敗寫操作,您可以執行以下操作:
while(size > 0) {
int written = write(filedes, buf, size);
if (written == -1) {
if (errno == EINTR) continue;
return -1;
}
buf += written;
size -= written;
}
return 0; // success
或者對於表現更好的東西,重試EINTR,盡可能多地寫入,並報告失敗時寫入多少(因此調用者可以決定是否以及如何繼續部分寫入因為信號中斷之外的原因而失敗):
int total = 0;
while(size > 0) {
int written = write(filedes, buf, size);
if (written == -1) {
if (errno == EINTR) continue;
return (total == 0) ? -1 : total;
}
buf += written;
total += written;
size -= written;
}
return total; // bytes written
GNU有一個非標准的TEMP_FAILURE_RETRY宏,可能會引起我的興趣,但是當我想要它時,我永遠找不到它的文檔。 包括現在。
另見更糟糕的“失敗者模式”的討論
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.