【问题标题】:signal handler ending the process after its execution信号处理程序在执行后结束进程
【发布时间】:2021-01-09 21:16:39
【问题描述】:

我正在编写一个程序,并为SIGINT 设置了一个信号处理程序:

volatile int exit_program = 0; //Global variable

void exit_client() {
    write(1, "Disconnecting...\n", strlen("Disconnecting...\n"));
    exit_program = 1;
}

然后我主要告诉进程在收到SIGINT 时对exit_client() 做出反应。

int main() {
    signal(SIGINT, exit_client);
    //...
}

稍后在主进程中我有以下代码:

while (!exit_program) {

    //...

    socket_rcv(server_socket);
}

close(server_socket);
write(1, "Disconnected\n", strlen("Disconnected\n"));
    

我使用socket_rcv() 从服务器套接字接收数据,如果read() 返回值为0(当服务器断开连接时),我还向进程发送SIGINT。我这样做执行:raise(SIGINT):

socket_data socket_rcv(int socket) {
        
    //...

    do {
        bytes_read = read(socket, sequence + (115 - total_bytes), total_bytes+10);

        if (bytes_read == -1) write(1, "Read error\n", strlen("Read error\n"));
        if (bytes_read == 0) raise(SIGINT);
        total_bytes -= bytes_read;

    } while (total_bytes > 0);

    //...
}

但是,当同时执行服务器和客户端并首先断开服务器连接时,看看客户端如何反应(应该打印Disconnecting... 然后Disconnected 以及服务器套接字关闭),我只得到打印信号处理程序确认信号处理程序执行但随后程序终止并且它不会继续执行以关闭套接字并执行最后一个write(1, "Disconnected\n", strlen("Disconnected\n"));

为什么会终止,我该如何解决?

另外,可能无关紧要,但 socket_rcv() 函数在另一个 .c 文件中声明,包括主进程所在的 .h 模块。

【问题讨论】:

  • 为什么需要信号?为什么不直接设置exit_program
  • 你能创建一个minimal reproducible example吗?
  • 请注意,一般情况下最好使用sigaction 而不是signal
  • @kaylum 因为程序直到我按下CTRL + C 才会结束,这会向该进程发送SIGINT 然后退出循环并free() 使用内存并关闭一些文件描述符
  • 不确定按 Ctrl+C 是否适合图片,您可能希望将其整合到整个故事中。请注意signal() 正在安装一次性处理程序,如果您获得两个信号,第二个将使用默认处理程序并立即核对进程。 raise 不会退出 socket_rcv 函数,所以你可能会得到断开连接的打印,回到被困在 socket_rcv 中,然后按 ^C 并见上文。

标签: c signal-handling


【解决方案1】:

我同意评论者的观点,既然可以直接设置exit_program,为什么还要使用信号处理程序?

无论如何,您的问题似乎出在其他地方(可能是read?),或者您没有向我们提供完整的图片,因为这段代码有效:

#include <signal.h>
#include <string.h>
#include <unistd.h>

volatile int exit_program = 0;

void exit_handler(int sig) {
    write(1, "exit_handler\n", strlen("exit_handler\n"));
    exit_program = 1;
}

int main() {
    int i = 0;

    signal(SIGINT, exit_handler);

    while (!exit_program) {
        write(1, "loop\n", strlen("loop\n"));

        if (i == 1) {
            raise(SIGINT);
        }

        ++i;
    }

    write(1, "done\n", strlen("done\n"));

    return 0;
}

打印

loop
loop
exit_handler
done

【讨论】:

    猜你喜欢
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多