简体   繁体   中英

How to terminate a program using SIGALRM

So basically I have 4-5 functions in my program. It is a lot of lines of codes and reading and writing from a file and it could end in an infinite loop (worse case) and I would like to terminate my program if it goes beyond lets say 20 seconds. below code is not working, my program hangs and the OS terminates it for me instead of the program terminating itself. I think the main problem I am having is the alarm is set in the main and when the alarm time limit is reached the process is executing in another function and this is causing the program to shut without closing files and killing child processes. This is what I have for now:

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;
}

there is only a certain set of function which can be executed safely from a signal handler. And exit is not one of them. Neither is printf .

You might able to use the _exit() function instead (with underscore in front). However it will only exit the top-most process, leaving the children running.

You can still kill everything using kill(0, signal) , as here.

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

Here is an example of a working poc code:

#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;
}

So after spending more than 24 hrs trying to fix this. The solution was actually simple. Keep a global array of PID of children alive +1 for parent PID. before sending the kill(PID, SIGTERM) we have to mention a handler for SIGTERM which sleeps till the process is killed. Thus a graceful exit.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM