【问题标题】:How to terminate a c program after 20 seconds如何在 20 秒后终止 c 程序
【发布时间】:2020-01-20 01:47:29
【问题描述】:

我试图在 20 秒后终止我的具有多个功能的 c 程序(杀死所有子进程和父进程,关闭文件)。我试过闹钟(),定时器(),时钟()。当我们只有一个主函数和一个处理函数时,它就可以工作。即使我将变量保持为全局变量,clock() 也会在每个函数中从 0 重新开始。

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include<stdbool.h>
#include <ctype.h>
#include<sys/wait.h>
#include<signal.h>
#include <sys/mman.h>
#include<sys/time.h>
#define INTERVAL 2
int t=0;
void display_message()
{
    printf("In the handler");
    //kill(0,SIGKILL);
    t=1;
}
void calling2()
{
    signal(SIGALRM, display_message);

    sleep(3);

}
void calling()
{

    signal(SIGALRM, display_message);
    alarm(2);

        int i;
        for(i=0;i<3;i++)
                {
                    //printf("\nStarting fork for loop i=%d \n",i);


                     pid_t pID = fork();

                       if (pID == 0)                // child
                       {
                           calling2();
                           if(t==1)
                           {
                               printf("we have exceeded 2 seconds killing the process");
                               kill(0,SIGKILL);
                               exit(0);
                           }
                        exit(0);
                        kill(pID,SIGKILL);
                       }
                       else if(pID>0)
                       {
                             //  printf("\nhello from the father");
                            if(t==1)
                                                       {
                                                           printf("killing the process");
                                                           kill(0,SIGKILL);
                                                           exit(0);
                                                       }
                            printf("\nhello from the father");
                       }
                }
}

如您所见,我尝试从不同的函数调用信号,以便它可以捕获信号并且处理程序可以执行但处理程序永远不会执行。

编辑:再试一次

# include <unistd.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <time.h>
# include <stdlib.h>
# include <dirent.h>
# include <stdio.h>
# include <string.h>
# include <getopt.h>
# include<stdbool.h>
# include <ctype.h>
# include<sys/wait.h>
# include<signal.h>
# include <sys/mman.h>
# include<sys/time.h>
# define INTERVAL 2
int t=0;
void display_message()
{

    kill(0,SIGKILL);
    t=1;
}
void calling2()
{

    sleep(3);

}
void calling()
{

    signal(SIGALRM, display_message);


        int i;
        for(i=0;i<3;i++)
                {

                     pid_t pID = fork();

                       if (pID == 0)                // child
                       {
                           calling2();
                           if(t==1)
                           {
                               printf("killing the process");
                               kill(0,SIGKILL);
                               exit(0);
                           }
                        exit(0);

                       }
                       else if(pID>0)
                       {
                                                        if(t==1)
                                                       {
                                                           printf("killing the process");
                                                           kill(0,SIGKILL);
                                                           exit(0);
                                                       }
                            printf("\nhello from the father");
                       }
                }
}
int main()
{
    signal(SIGALRM, display_message);
    alarm(2);
    calling();
}
O/P:
hello from the father
hello from the father
hello from the father
hello from the father
hello from the father
hello from the father
error: Failed with return code 22

【问题讨论】:

  • You shouldn't use printf() in a signal handler,无论是直接调用还是间接调用。
  • 调用序列exit(0); kill(pID,SIGKILL); 应该会丢失kill()exit() 不会返回。此外,在编程中,一致性很重要(对于高质量的代码)。例如,#include 和标题名称之间应始终有一个空格,无论是 #include &lt;stdbool.h&gt; 还是 #include "project.h"
  • 要杀死所有子进程,您需要在某处列出子 PID。好吧,我想你可以试试kill() 的一些特殊情况——pid 的值0-1 甚至-getpgrp() 可能是你杀死进程所需要的。当进程终止时,所有文件都会关闭。除非您在某个地方有所有打开文件的列表,否则最好将其留给系统。因此,您需要决定是 kill(0, SIGTERM) 还是 kill(-1, SIGHUP) 或其他什么东西会为您完成这项工作。
  • 在 EDIT 中添加了更改。还是不行

标签: c fork clock


【解决方案1】:

主要问题是您的主线程在处理警报信号之前完成。您必须至少让它存活,直到发出警报信号。此外,正如 Jonathan Leffler 建议的那样,良好的缩进/间距确实很有帮助。

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <time.h>
#include <stdlib.h>
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <getopt.h>
#include <stdbool.h>
#include <ctype.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/time.h>

#define INTERVAL 2
int t=0;

void display_message()
{
    kill(0,SIGKILL);
    t=1;
}

void calling2()
{

    sleep(3);
}

void calling()
{

    signal(SIGALRM, display_message);
    int i;
    for(i=0;i<3;i++)
    {
        pid_t pID = fork();
        if (pID == 0)                // child
        {
            calling2();
            if(t==1)
            {
                printf("killing the process");
                kill(0,SIGKILL);
                exit(0);
            }
            exit(0);
        }
        else if(pID>0)
        {
            if(t==1)
            {
                printf("killing the process");
                kill(0,SIGKILL);
                exit(0);
            }
            printf("\nhello from the father");
        }
    }
}

int main()
{
    signal(SIGALRM, display_message);
    alarm(2);
    calling();

    //  wait until alarm callback before terminating main thread
    sleep(100);
}

【讨论】:

  • 睡眠功能不会导致程序在这 100 秒内不做任何事情吗? main 完成并将执行传递给其他函数。是否可以设置警报或定时中断,一旦设置,无论程序在哪里执行,警报或中断都会在 20 秒后处理?
  • 另外,这会让我退出 linux 服务器,退出状态为 143。我只想终止程序,而不是退出服务器。你认为有办法做到这一点吗?
  • 关于您的第一点:“是否可以设置警报或定时中断,以便一旦设置,警报或中断将在 20 秒后处理”,您已经使用 SIGALRM 做到了.但是你在这里写的重要一点是“无论程序在哪里执行”。无需等待,您的警报回调不会被调用,因为您的主进程在创建子进程后立即完成(它到达主进程的末尾)。你可以用其他东西代替等待,比如等待输入,做很多事情等等,只是防止主进程在警报响起之前完成。
  • 关于注销事情:当你的警报响起时,你是要杀死所有的子进程还是只杀死主要的父进程?如果您只想杀死父进程,请将 kill(0, SIGKILL) 替换为 exit(0)。如果您还想杀死所有孩子,请将他们的 pid 保存在数组/列表中并向所有孩子发送终止消息,然后退出主进程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-25
  • 2017-07-10
  • 1970-01-01
  • 2017-04-21
相关资源
最近更新 更多