[英]parent shell not getting SIGINT when child has a handler
當您按 Ctrl-C 時,前台進程會收到 SIGINT:
$ bash -c 'sleep 100; echo program died'
^C
$ echo $?
130
但是,如果程序安裝了 SIGINT 處理程序,則父程序不會收到信號。 為什么?
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
void sig_int(int sig_num)
{
exit(1);
}
static struct sigaction sigact = { .sa_handler=sig_int };
int main(int argc, char *argv[])
{
sigaction(SIGINT,&sigact,NULL);
sleep(100);
return 0;
}
bash 沒有死:
$ bash -c './a.out; echo program died'
^Cprogram died
與Bash not trapping interrupts during rsync/subshell exec statements 相關,但所有答案都有解決方法。
這個長后解釋什么是細節發生。 在這里,我將嘗試總結最重要的概念並提出一個可行的解決方案。
事實證明,如果SIGINT不是直接從終端發送的(通過按CTRL-C
),則 shell 被編程為忽略SIGINT 。 如果子進程攔截了它,那么它必須通過使用SIGINT顯式殺死自己來退出,引用帖子:
“如果你沒有捕捉到 SIGINT,系統會自動為你做正確的事情:你的程序退出,調用程序在等待你退出后獲得正確的“I-exited-on-SIGINT”狀態。
但是一旦你捕捉到 SIGINT,你必須在你的 SIGINT 處理程序中進行任何清理之后采取正確的退出方式。
決定 SIGINT 是否用於退出/中止目的,因此調用該程序的 shellscript 應該停止。 希望這是顯而易見的。 如果您只需要對 SIGINT 進行一些清理,然后立即退出,那么答案是“是”。
如果是這樣,您必須通過以“I-exited-on-SIGINT”狀態退出來告訴調用程序有關它的信息。
除了用 SIGINT 信號殺死自己之外,沒有其他方法可以做到這一點。 通過將 SIGINT 處理程序重置為 SIG_DFL 來實現,然后向自己發送信號。
void sigint_handler(int sig) { [do some cleanup] signal(SIGINT, SIG_DFL); kill(getpid(), SIGINT); }
信號處理程序
這是攔截信號並正確殺死自己的處理程序的工作版本(因此它不會打印“程序死亡”)。 OTOH,如果您發送不同的信號,處理程序將運行exit
函數,您將再次在屏幕上看到“程序已死”。
void sig_int(int sig_num)
{
if (sig_num == SIGINT) {
printf("received SIGINT\n");
signal(SIGINT, SIG_DFL);
kill(getpid(), SIGINT);
} else {
exit(1);
}
}
static struct sigaction sigact = { .sa_handler=sig_int };
int main(int argc, char *argv[])
{
sigaction(SIGINT,&sigact,NULL);
printf("go to sleep\n");
sleep(3);
printf("awaken\n");
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.