正确清理信号处理函数

Correct cleaning at signal handler function

我制作了一个程序,它使用 fork() 函数来创建子进程。它的子进程做一些工作,但我希望它们在收到来自父进程的 SIGTERM 信号时终止。在退出之前,我还希望他们清理我分配的数组并通过 FIFO 将一些东西发送到父进程。所以我有两种情况。

  1. 我的数组的全局变量以及 FIFO 的文件描述符,然后通过信号处理函数退出,例如:

    /*global variables*/
    struct whatever ** test;
    int test_size;
    int fd_in, fd_out;
    
    /*handler*/
    void shutdown(int signo)
    {
          /*free memory for the arrays malloc'd through the program*/
          /*send message with the help of fd_out*/
          /*close fd_in and fd_out*/
          _exit(0);
    }
    
  2. 声明一个global int flag,当子进程感知到flag发生变化时,它们会清理数组,发送消息并退出。

    /*global variables*/
    int exit_flag=0;
    
    /*handler*/
    void shutdown(int signo)
    {
          exit_flag=1;
    }
    
    /*child process*/
    int main()
    {
          /*declare fds and arrays*/
          /*use sigaction and set up handler*/
    
          while(!exit_flag)
          {
                 /*do stuff*/
          }
    
          /*free memory*/
          /*send message with the help of fd_out*/
          /*close fds*/
    }
    

我的问题是哪种情况会导致好的 coding/programming?它们是相同的还是有更好甚至更正确的方法来做到这一点?

你的第二个实现比你的第一个更不容易出错。如果您是 freeing/closing 资源,则必须确定活动进程未使用这些资源。由于您正在接收异步信号,因此没有好的方法可以确定您的进程处于合适的状态以在没有竞争条件的情况下释放这些资源。

此外,您很可能还需要在其他情况下(错误、完成等)执行这些清理例程,因此如果在处理程序中实现这些例程可能是多余的。

另外,最好养成将全局标志声明为 volatile 的习惯,以确保您的编译器不会将标志优化为常量并让您陷入无限循环.

volatile int exit_flag=0;