代码之家  ›  专栏  ›  技术社区  ›  ollien

sigaction将SIGINT传递给系统调用,但不传递信号

  •  1
  • ollien  · 技术社区  · 6 年前

    我有一个循环处理一个 accept(2) 打电话。我想在一个 SIGINT signal 功能。

    void signal_handler(int signal) {
        printf("Caught signal\n");
    }
    
    int main() {
        signal(SIGINT, &signal_handler);
        // ...
        int accept_fd = accept(sock, NULL, NULL);
        if (accept_fd == -1) {
            close(sock);
            perror("accept");
            return 1;
        }
        // ...
    }
    

    如果我修改 main 使用 sigaction

    int main() {
        struct sigaction sa;
        sa.sa_handler = &signal_handler;
        sa.sa_flags = 0;
        sigemptyset(&sa.sa_mask);
        sigaction(SIGINT, &sa, NULL);
        // ...
        int accept_fd = accept(sock, NULL, NULL);
        if (accept_fd == -1) {
            close(sock);
            perror("accept");
            return 1;
        }
        // ...
    }
    

    发送信号后,我得到 Caught Signal ,后跟 accept: Interrupted system call . 从手册页 接受(2)

    错误

    EINTR系统调用被在有效连接到达之前捕获的信号中断;请参阅信号(7)。

    我明白 更现代,我应该多用一次 信号 ,但我很好奇为什么它提供了这种功能上的差异。

    下面我为每个案例提供了一个完整的可用示例程序。

    信号示例(2)

    #include <netdb.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    
    #define BUFFER_SIZE 32
    
    void signal_handler(int signal) {
        printf("Caught signal\n");
    }
    
    int main() {
        signal(SIGINT, &signal_handler);
        struct addrinfo hints;
        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        struct addrinfo *addr_info;
        int info_result = getaddrinfo("localhost", "8080", &hints, &addr_info);
        if (info_result != 0) {
            printf("Getting address failed\n");
            return 1;
        }
        int sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
        if (sock == -1) {
            printf("Socket Failed\n");
            return 1;
        }
        int bind_result = bind(sock, addr_info->ai_addr, addr_info->ai_addrlen);
        if (bind_result == -1) {
            close(sock);
            printf("Bind Failed\n");
            return 1;
        }
        int listen_result = listen(sock, 8);
        if (listen_result == -1) {
            close(sock);
            printf("Listen Failed\n");
            return 1;
        }
        printf("Waiting...\n");
        int accept_fd = accept(sock, NULL, NULL);
        if (accept_fd == -1) {
            close(sock);
            perror("accept");
            return 1;
        }
        printf("Got fd %d\n", accept_fd);
        char *buffer = malloc(BUFFER_SIZE * sizeof(char));
        int n;
        while ((n = read(accept_fd, buffer, BUFFER_SIZE)) > 0) {
            printf("%.*s\n", n, buffer);
        }
        close(sock);
    }
    

    #include <netdb.h>
    #include <signal.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <unistd.h>
    
    #define BUFFER_SIZE 32
    
    void signal_handler(int signal) {
        printf("Caught signal\n");
    }
    
    int main() {
        struct sigaction sa;
        sa.sa_handler = &signal_handler;
        sa.sa_flags = 0;
        sigemptyset(&sa.sa_mask);
        sigaction(SIGINT, &sa, NULL);
        struct addrinfo hints;
        memset(&hints, 0, sizeof(struct addrinfo));
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        struct addrinfo *addr_info;
        int info_result = getaddrinfo("localhost", "8080", &hints, &addr_info);
        if (info_result != 0) {
            printf("Getting address failed\n");
            return 1;
        }
        int sock = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol);
        if (sock == -1) {
            printf("Socket Failed\n");
            return 1;
        }
        int bind_result = bind(sock, addr_info->ai_addr, addr_info->ai_addrlen);
        if (bind_result == -1) {
            close(sock);
            printf("Bind Failed\n");
            return 1;
        }
        int listen_result = listen(sock, 8);
        if (listen_result == -1) {
            close(sock);
            printf("Listen Failed\n");
            return 1;
        }
        printf("Waiting...\n");
        int accept_fd = accept(sock, NULL, NULL);
        if (accept_fd == -1) {
            close(sock);
            perror("accept");
            return 1;
        }
        printf("Got fd %d\n", accept_fd);
        char *buffer = malloc(BUFFER_SIZE * sizeof(char));
        int n;
        while ((n = read(accept_fd, buffer, BUFFER_SIZE)) > 0) {
            printf("%.*s\n", n, buffer);
        }
        close(sock);
    }
    
    1 回复  |  直到 4 年前
        1
  •  3
  •   John Zwinck    6 年前

    在BSD和Linux上, signal() 相当于 sigaction() 具有 sa_flags 设置为 SA_RESTART . 如果你把旗子放在你的 sigaction() 代码,它的行为与 sigaction() .

    来自 Linux man page

    在BSD上, 当一个信号处理程序被调用时,信号的配置是不正确的 在处理程序执行时传递。此外,某些 阻塞系统调用在被中断时自动重新启动 使用以下标志调用sigaction(2):

           sa.sa_flags = SA_RESTART;