【问题标题】:How to terminate a program using SIGALRM如何使用 SIGALRM 终止程序
【发布时间】:2019-09-18 00:42:08
【问题描述】:

所以基本上我的程序中有 4-5 个函数。这是很多行代码以及从文件中读取和写入的内容,它可能以无限循环结束(更糟糕的情况),如果它超过 20 秒,我想终止我的程序。下面的代码不起作用,我的程序挂起,操作系统为我终止它,而不是程序自行终止。我认为我遇到的主要问题是在主程序中设置了警报,当达到警报时间限制时,进程正在另一个函数中执行,这导致程序在没有关闭文件并杀死子进程的情况下关闭。这就是我现在所拥有的:

volatile sig_atomic_t keep_going = 1;

/* The signal handler just clears the flag and re-enables itself. */
void
catch_alarm (int sig)
{
    printf("Alarm went off");
  exit(EXIT_SUCCESS);
}
void function1
{}
void forkingfunction()
{
or(i=0;i<size;i++,temp++)
        {

             pid_t pID = vfork();

               if (pID == 0)                // child
               { 
                   printf("\nchild pid %d\n",getpid());
                    //open some files and read and write
                     function1();
                      exit(EXIT_SUCCESS);
                       kill(pID,SIGKILL);
                       }
               }
               else if (pID < 0)            // failed to fork
               {
                   perror("Failed to fork:");
               }
}
void function2
{
function1();
}
int main()
{
int options
while(options){
switch (options)
{
case 1:
case 2:
}
}
signal (SIGALRM, catch_alarm);

          alarm (0.1);//testing for 0.1 seconds 
function1();

return 0;
}

【问题讨论】:

  • 这甚至不能编译。请发布一个最小的、可重现的示例。

标签: c vfork


【解决方案1】:

只有一组特定的函数可以从信号处理程序中安全地执行。 exit 不是其中之一。 printf 也不是。

您也许可以改用_exit() 函数(前面带有下划线)。但是它只会退出最顶层的进程,让子进程继续运行。

你仍然可以使用kill(0, signal) 杀死所有东西,就像这里一样。

void catch_alarm (int sig) {
   kill(0, SIGTERM);
}

这是一个工作 poc 代码的示例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>

void catch_alarm (int sig) {
    kill (0,SIGTERM);
}

void forkingfunction()
{
    int i;
    for(i=0;i<4;i++,i++) {
        pid_t pID = fork();
        if (pID == 0) { 
            sleep(5);
            printf("\nchild pid %d\n",getpid());
            exit(EXIT_SUCCESS);
        }
        else if (pID < 0) {
            perror("Failed to fork:");
        }
    }
}
int main()
{
    signal (SIGALRM, catch_alarm);
    alarm (1);//testing for 0.1 seconds 
    forkingfunction();
    sleep(10);
    printf("\nnormal exit\n");
    return 0;
}

【讨论】:

  • 您的代码,就像现在一样,可能永远循环在while (options) 循环中,甚至没有机会设置处理程序或警报。此外,由于语法问题,它根本无法编译。我用一个工作示例更新了我的答案。
  • sleep(10)执行时程序不会什么都不做吗?
  • 我尝试了这个例子,但不是仅仅终止它,而是让我退出 linux 服务器并说“连接已意外关闭,服务器发送命令退出状态 143”
  • 现在你必须弄清楚你想做什么。我想在您的情况下,您需要在处理程序中保留所有活着的孩子的列表并一个一个地杀死它们(kill(childpid,SIGTERM)),然后使用_exit(0)_Exit(0) 以正常状态退出。这需要您进行一些编程。
  • void handler(int sig) { exit(0); } void catch_alarm (int sig) { int i; for(i=0;i
【解决方案2】:

所以在花了超过 24 小时试图解决这个问题之后。解决方案实际上很简单。保持孩子的全局 PID 数组存活 +1 为父 PID。在发送 kill(PID, SIGTERM) 之前,我们必须提到 SIGTERM 的处理程序,它会一直休眠直到进程被杀死。从而优雅地退出。

【讨论】:

    猜你喜欢
    • 2021-05-16
    • 1970-01-01
    • 1970-01-01
    • 2019-08-05
    • 2011-08-29
    • 2014-01-17
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    相关资源
    最近更新 更多