[英]Reset mask of ignored signal in Linux
在exec()
期間,阻塞信號的掩碼(由sigprocmask()
設置)由子進程繼承。
但是現在我注意到在 Linux 下,還有忽略信號的掩碼( grep < /proc/self/status ^SigIgn
),它也被子進程繼承。 由於這些是由sigaction()
和act.sa_handler = SIG_IGN
設置的,所以我預計,作為信號處理程序,它們會在執行期間被重置。 但他們不是。
考慮下面的例子:父母想要忽略 SIGINT,但這也延伸到孩子,因此不能用kill -INT $(pidof sleep)
sleep 120
。
問題:
這是否符合 POSIX? sigaction()的文檔明確指出sigaction
的效果在exec
中不存在(引用:“ ......直到調用其中一個 exec 函數”)。 Linux 手冊頁說“忽略信號的配置保持不變”,我猜這是 Linux 的特定功能。
如何正確可靠地重置忽略掩碼? 我沒有發現sigprocmask()
的模擬 - 管理阻塞的信號 - 來管理忽略信號的掩碼。 我應該簡單地遍歷所有信號並使用sigaction()
重置它們嗎?
PS 使用內核 v3.x 和 v4.9 測試,行為相同。
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
struct sigaction act;
sigset_t ss;
system("grep -n < /proc/self/status ^SigIgn");
memset(&act, 0, sizeof(act));
act.sa_handler = SIG_IGN;
sigaction( SIGINT, &act, NULL );
system("grep -n < /proc/self/status ^SigIgn");
sigemptyset(&ss);
sigprocmask(SIG_SETMASK, &ss, NULL);
system("grep -n < /proc/self/status ^SigIgn");
system("sleep 120");
return 0;
}
- 這是否符合 POSIX?
是的, https://pubs.opengroup.org/onlinepubs/9699919799/functions/exec.html指定:
在調用進程映像中設置為默認操作(SIG_DFL)的信號應設置為新進程映像中的默認操作。 除 SIGCHLD 外,調用進程映像設置為忽略的信號 (SIG_IGN) 應設置為被新進程映像忽略。 設置為由調用過程映像捕獲的信號應設置為新過程映像中的默認操作(請參閱 )。
(強調我的)
阻塞信號掩碼、默認信號掩碼和忽略信號掩碼都在 POSIX 中的exec*
調用中繼承,盡管 POSIX 並沒有后兩個掩碼的概念(它們只是特殊的信號處置,設置為每個信號單獨進行,與可以整體修改的阻塞信號掩碼不同)。
- 如何正確可靠地重置忽略掩碼? 我沒有發現 sigprocmask() 的模擬 - 管理阻塞的信號 - 來管理忽略信號的掩碼。 我應該簡單地遍歷所有信號並使用 sigaction() 重置它們嗎?
是的——使用sigaction
或signal
遍歷信號。 (雖然sigaction
應該是首選,但對於將信號設置為SIG_IGN
/ SIG_DFL
,信號足夠、可移植且更緊湊。)。 理想情況下,這應該在fork()
之后完成,以防止與其他線程競爭(信號處置是共享的全局狀態)。
更好的是,您可以將posix_spawn
/ posix_spawnp
與一個屬性 ( posix_spawnattr_t
) 一起使用,該屬性指定應在子進程中重置為默認值的信號集。 posix_spawnattr_setsigdefault
屬性設置器可用於指定此信號集。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.