无法更改 SIGINT 的默认操作
Cannot change default action for SIGINT
在 C 中,我想捕获 SIGINT
信号并打印出一条消息,例如
"SIGINT received" 通过使用 sigaction 并通过
将新的处理程序传递给它
sa.sa_sigaction = handler;
我不想终止程序。
如果我 运行 我的程序通过 shell 并使用 Ctrl+c 生成信号,信号处理程序将捕获信号并打印出我的消息。
之后,它将执行终止进程的默认操作。
我做错了什么?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
static void handler(int sig, siginfo_t* si, void *unused){
if(sig == SIGINT){
printf("Signal %i received\n",si->si_signo);
}
}
int main(int argc, char* argv[]){
char s [256];
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGINT);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
if(sigaction(SIGINT, &sa, NULL) < 0 ){
perror("sigaction");
}
fgets(s,sizeof(s), stdin);
printf("%s", s);
return 0;
}
问题是 fgets
会调用 read
系统调用,系统调用会 return 被 SIGINT
中断时出错,参见 read 的手册页:
EINTR The call was interrupted by a signal before any data was read; see signal(7).
所以你应该检查 fgets
的 errno
如果是 EINTR
继续调用 fgets
。试试我更新的程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
static void handler(int sig, siginfo_t* si, void *unused){
if(sig == SIGINT){
printf("Signal %i received\n",si->si_signo);
}
}
int main(int argc, char* argv[]){
char s [256];
struct sigaction sa = {0};
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGINT);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
if(sigaction(SIGINT, &sa, NULL) < 0 ){
perror("sigaction");
}
char *p;
do {
p = fgets(s,sizeof(s), stdin);
} while (!p && errno == EINTR);
printf("%s\n", s);
return 0;
}
在 C 中,我想捕获 SIGINT
信号并打印出一条消息,例如
"SIGINT received" 通过使用 sigaction 并通过
sa.sa_sigaction = handler;
我不想终止程序。
如果我 运行 我的程序通过 shell 并使用 Ctrl+c 生成信号,信号处理程序将捕获信号并打印出我的消息。
之后,它将执行终止进程的默认操作。
我做错了什么?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
static void handler(int sig, siginfo_t* si, void *unused){
if(sig == SIGINT){
printf("Signal %i received\n",si->si_signo);
}
}
int main(int argc, char* argv[]){
char s [256];
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGINT);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
if(sigaction(SIGINT, &sa, NULL) < 0 ){
perror("sigaction");
}
fgets(s,sizeof(s), stdin);
printf("%s", s);
return 0;
}
问题是 fgets
会调用 read
系统调用,系统调用会 return 被 SIGINT
中断时出错,参见 read 的手册页:
EINTR The call was interrupted by a signal before any data was read; see signal(7).
所以你应该检查 fgets
的 errno
如果是 EINTR
继续调用 fgets
。试试我更新的程序:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
static void handler(int sig, siginfo_t* si, void *unused){
if(sig == SIGINT){
printf("Signal %i received\n",si->si_signo);
}
}
int main(int argc, char* argv[]){
char s [256];
struct sigaction sa = {0};
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGINT);
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = handler;
if(sigaction(SIGINT, &sa, NULL) < 0 ){
perror("sigaction");
}
char *p;
do {
p = fgets(s,sizeof(s), stdin);
} while (!p && errno == EINTR);
printf("%s\n", s);
return 0;
}