c - 捕获SIGINT信号后退出程序

标签 c parallel-processing client sigint

我有一个使用 OpenMP 实现的客户端应用程序。该程序在收到 SIGINT 信号时终止,但在这种情况下,它应该首先向服务器发送一条消息,指示用户已注销。我已经成功实现了消息传递,但我无法让程序随后终止。

这是我的代码的并行部分:

#pragma omp parallel num_threads(4)
{
    #pragma omp sections
    {
        #pragma omp section
        {
            while(1)
            {
                char pom[1000];
                fgets(pom, 1000, stdin);
                if (strlen(pom) != 1)
                {
                    char * buffer;
                    buffer = message(username, pom);
                    if (send(client_socket, buffer, strlen(buffer), 0) < 0)
                    {
                        callError("ERROR: cannot send socked");
                    }
                    bzero(pom, 1000);
                    free(buffer);
                }
            }
        }
        #pragma omp section
        {   
            char buffer[4096];
            char * data;
            ssize_t length;
            int received = 0;
            int data_cap = 4096;
            while(1)
            {
                data = calloc(BUFFER_LEN, sizeof(char));
                while ((length = read(client_socket, buffer, BUFFER_LEN)) > 0)
                {
                    received += length;
                    if (received > data_cap)
                    {
                         data = realloc(data, sizeof(char) * data_cap * 2);
                         data_cap = data_cap * 2;
                    }
                    strcat(data, buffer); 
                    if (!isEnough(data))
                    {
                        break;
                    }
                }
                printf("%s", data);
                free(data);
                bzero(buffer, BUFFER_LEN);
                data_cap = 4096;
                received = 0;
                length = 0;
            }
        }
        #pragma omp section
        {
            void sig_handler(int signo)
            {
                char * welcome1 = calloc(strlen(username) + 13, sizeof(char));
                strcat(welcome1, username);
                strcat(welcome1, " logged out\r\n");
                if (send(client_socket, welcome1, strlen(welcome1), 0) < 0)
                {
                    callError("ERROR: cannot send socked");
                }
                free(welcome1);
            }

            while (1)
            {
                if (signal(SIGINT, sig_handler) == SIG_ERR)
                    printf("\ncan't catch SIGINT\n");
                while (1)
                    sleep(1);
            }
        }
    }

如何让程序在捕获信号后终止?

最佳答案

您的程序有几个严重的问题。

首先,您尝试将信号处理函数定义为嵌套函数。 C 没有嵌套函数。您的代码能够编译必然意味着您依赖于语言扩展,并且将其与信号处理并置似乎特别不明智。

你调用一个函数callError()从信号处理程序内部。目前尚不清楚该函数是否是异步信号安全的。您调用函数calloc() , strcat() ,和free()从信号处理程序内部。这些绝对不是异步信号安全的,并且不能从信号处理程序内部调用。

您为并行构造招募了四个线程,但只提供了三个要运行的部分。

您将所有并行部分放入无限循环中(因此当然程序不会在捕获已安装处理程序的信号时终止)。

您没有始终如一地检查函数调用的返回值。

<小时/>

您的总体策略似乎很困惑。一般来说,执行干净的异步关闭(即导致线程终止操作以响应不同线程或信号处理程序的操作)涉及设置一个共享标志,要关闭的线程定期检查该标志确定是继续还是退出。您可以安全地从信号处理程序设置此类标志,前提是其类型为 volatile sig_atomic_t .

此外,信号处理程序应该执行尽可能少的工作,并且允许它们调用的系统函数仅限于指定的异步信号安全函数。此外,它们可能会使用小堆栈进行操作,您应该小心,不要冒耗尽堆栈的风险。

此外,等到进入 OMP 并行 block 后才安装信号处理程序没有任何优势,并且让信号处理程序将终止消息发送到服务器本身也没有任何优势。

由于您似乎完全满足于将线程专用于信号处理,因此我建议您使用它来接受 SIGINT 同步,通过 sigwait()或其相关功能之一。然后该线程可以触发 OMP 的取消功能 - 请参阅 cancel-var ICV 和 cancel构造。其他线程需要合作 - 请参阅 cancellation point构造。由于您没有提供退出并行部分的其他方法,因此您可以从正常(不是信号处理程序)代码将注销消息发送到服务器,紧随并行区域。

关于c - 捕获SIGINT信号后退出程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43329810/

相关文章:

c - 变量被视为未初始化

c - 为什么 getopt 库中没有 <string.h>?

c# - 无法在 Visual C# 项目中使用我的 .dll

python - 与多处理队列作斗争

c++ - 并发 : C++11 memory model for shared variables in multithreaded environment

来自服务器端的 C++ 套接字主机名

python - 用于发送字符串数据的简单 rpyc 客户端和服务器

c++ - 将 C++ 类转换为过程 API : common way of replacing member variables?

python - 如何在 Python 中加速矩阵乘法?

c - 函数接收 char * 就好像它是空的