4

I am trying to terminate my c program with multiple functions after 20 seconds (kill all child and parent processes, close files). I tried alarm(), itimer(), clock(). It works when we only have a main and a handler function. clock() restarts from 0 in every function even if I keep the variables global.

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

As you can see I tried calling signal from different functions so it can catch the signal and the handler can execute but the handler is never executed.

EDIT: Tried this again

# 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
Fairy
  • 101
  • 2
  • 12
  • have you had a look at this: https://cboard.cprogramming.com/c-programming/139486-exit-program-using-timer.html – DoubleRainbowZ Sep 19 '19 at 05:31
  • 2
    [You shouldn't use `printf()` in a signal handler](https://stackoverflow.com/questions/16891019/), whether invoked directly or indirectly. – Jonathan Leffler Sep 19 '19 at 06:17
  • The call sequence `exit(0); kill(pID,SIGKILL);` should lose the `kill()` — `exit()` doesn't return. Also, in programming, consistency is important (for good quality code). For example, you should always have one space between `#include` and the header name, whether that's `#include ` or `#include "project.h"`. – Jonathan Leffler Sep 19 '19 at 06:21
  • 1
    To kill all child processes, you'll need a list of child PIDs somewhere. Well, I suppose you could try some of the special cases of [`kill()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/kill.html) — a `pid` value of `0` or `-1` or even `-getpgrp()` might be what you need to kill the processes. All files are closed anyway when a process is terminated. Unless you have somewhere a list of all open files, you're best off leaving that to the system. So, you need to decide whether `kill(0, SIGTERM)` or `kill(-1, SIGHUP)` or something else will do the job for you. – Jonathan Leffler Sep 19 '19 at 06:29
  • Added the changes in EDIT. Still not working – Fairy Sep 19 '19 at 06:40

1 Answers1

0

Main problem is your main thread is finished before alarm signal is handled. You must let it live at least until alarm signal is delivered. Also as Jonathan Leffler adviced good indentation/spacing is really helpful.

#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);
}
unlut
  • 3,525
  • 2
  • 14
  • 23
  • won't the sleep function cause the program to not do anything for those 100 seconds? The main finishes and passes the execution into other functions. Is it possible to setup an alarm or a timed interrupt such that once it is set, the alarm or interrupt will be handled after 20 seconds no matter where the program is executing ? – Fairy Sep 19 '19 at 14:43
  • Also, This logs me out of the linux server and exit status is 143. I just want to terminate the program, not log out of the server. do you think there is a way to do that? – Fairy Sep 19 '19 at 15:01
  • About your first point:"Is it possible to setup an alarm or a timed interrupt such that once it is set, the alarm or interrupt will be handled after 20 seconds", you already do that with SIGALRM. But important thing here you also write is "no matter where the program is executing". Without wait, your alarm callback is not called beucase your main process is instantly finishing after creating children (it reaches end of main). You can replace wait with other things like waiting for input, doing lots of stuff etc just prevent the main process from finishing before alarm goes off. – unlut Sep 19 '19 at 20:28
  • About logging out thing: When your alarm goes off, do you want to also kill all children or just the main parent process? If you just want to kill parent process replace kill(0, SIGKILL) with exit(0). If you also want to kill all children, save their pids in an array/list and send kill message to all of them then exit main process. – unlut Sep 19 '19 at 20:31