C语言&sigintHandler

C language & sigintHandler

突然点击"ctrl+c"想删除FIFO文件。我想捕获该信号,然后在实际终止进程之前删除之后的信号。 这是我的代码,我不知道出了什么问题:

 #include <fcntl.h>
 #include <stdio.h>
 #include  <stdlib.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <signal.h>
 #define MAX_BUF 512

 void sigintHandler(int sig_num,char * myfifo)
{
puts("hello you there .please don't leave ");
unlink(myfifo);
exit(0);
}

int main()
{

printf("Access-Control-Allow-Origin: *\n");
printf("Content-Type: text/event-stream\n\n");
int fd;
char buf[MAX_BUF];

char * myfifo = "/tmp/omcipipe";
struct stat st;

//捕捉 ctrl c

 sigaction(SIGINT, sigintHandler);



  //Create FIFO file 
     if (stat(myfifo, &st) != 0)
     mkfifo(myfifo, 0666);

 fd = open(myfifo, O_RDONLY);
while (read(fd, buf, MAX_BUF)>0)
{
    printf("data: %s", buf);
    printf("\n");
    fflush(stdout);
} 

puts( "----closing----"); 
close(fd);
unlink(myfifo);
return 0;

}

首先,您使用 sigaction() 设置信号处理程序的方式不正确,因为您没有填写 struct sigaction 的所有成员。填写所有必填成员

struct sigaction info;
info.sa_handler = sigintHandler;
sigaction(SIGINT,&info,NULL);

其次,从 fifo 文件读取数据 而循环 不需要,因为您一次读取 MAX_BUF。不需要循环,这样读

int ret = read(fd, buf, MAX_BUF);
buf[ret-1] = '[=11=]'; /*it should be null terminated */ 

第三,sigintHandler()只有一个参数除外。来自 sigaction()

的手册页
struct sigaction {
        void     (*sa_handler)(int);  /*handler expects only 1 argument */
        /* other member */
}

最后也是最重要的是,从信号处理程序中调用 printf()exit() 等函数是不安全的。

你的 sigHandler() 看起来像

static void sigintHandler(int sig_num) {
        write(1,"in isr\n",strlen("in isr\n"));
        /*  set some flag variable here & use that 
        flag variable in main() function to remove the fifo */
}

看到这个How to avoid using printf in a signal handler?

这是示例代码

static int fifo_flag = 0;
static void sigintHandler(int sig_num) {
        write(1,"in isr\n",strlen("in isr\n"));
        fifo_flag = 1;
}
int main(void){
        printf("Access-Control-Allow-Origin: *\n");
        printf("Content-Type: text/event-stream\n\n");
        int fd = 0, index = 0;
        char buf[MAX_BUF];
        #if 0
        char *myfifo = "data";
        #endif
        //char * myfifo = "/tmp/omcipipe";
        struct stat st;
        struct sigaction info;
        info.sa_handler = sigintHandler;
        //info.sa_flags = /* set to defaulgs a/c to your requirement*/

        if (stat(myfifo, &st) != 0) {
                mkfifo(myfifo, 0666);
                perror("mkfifo");
        }
        fd = open(myfifo, O_RDONLY | 0666);
        if(fd == -1){
                perror("open");
                return 0;
        }
        char ch = 0;
        while(read(fd, &ch, 1) > 0) {
                sigaction(SIGINT,&info,NULL);/* if ctrl+c  is called */
                buf[index] = ch;
                //sleep(1);/* just to observe ctrl+c behaviour, not advised to use */
                printf("%c\n",buf[index]);
                index++;
        }
        buf[index] = '[=14=]';
        printf("data: %s", buf);
        printf("\n");
        puts( "----closing----");
        close(fd);
        if(fifo_flag == 1) { /*if flag is set, unlink fifo */
                unlink(myfifo); /* you can unlink fifo file here */
        }
        return 0;
}

你的代码有很多问题。

此代码假定 read()'[=15=]' 字符终止数据:

while (read(fd, buf, MAX_BUF)>0)
{
    printf("data: %s", buf);
    printf("\n");
    fflush(stdout);
}

read() 仅读取原始字节,仅此而已。它不会正确终止带有 '[=15=]' 字符的字符串。所以 printf() 几乎肯定会调用未定义的行为。

这个代码

sigaction(SIGINT, sigintHandler);

完全错了。 sigaction() takes three parameters:

   #include <signal.h>

   int sigaction(int signum, const struct sigaction *act,
                 struct sigaction *oldact);

你也只能做出async-signal-safe function calls from within a signal handler。此代码

 void sigintHandler(int sig_num,char * myfifo)
{
puts("hello you there .please don't leave ");
unlink(myfifo);
exit(0);
}

调用 puts()exit(),两者都不是异步信号安全的。

并且如评论中所述,信号处理程序代码假定 myfifo 作为第二个参数传递。它不是。根据 the sigaction man page,第二个参数是 struct siginfo *,其中包含有关信号上下文的信息 - 但前提是 struct sigaction 传递给注册信号处理程序的 sigaction() 调用具有 SA_SIGINFO 标志集,并且使用 sa_sigaction 成员而不是 sa_handler 成员设置处理程序。