Search code examples
clinuxtimefork

fork() multiple times with a timer


I have this piece of code:

    int pidArr[128];
    int i=0;
    clock_t begin;
    double time_spent; 
    begin = clock();
    while(1) {
        time_spent = (double)(clock() - begin) / CLOCKS_PER_SEC; 
        if (time_spent>=2.0){ break; }
        pid = fork();
        if(pid == 0){
            pidArr[i] = getpid();
            i++;
        }
    }

I want to fork() for 2 seconds to fill my pid array and break from the loop but it's not happend & my virtual machine crash badly.

I'll appreciate any help to fix it.


Solution

  • You have accidentaly created a fork bomb, the problem is that when the timer is elapsed you should kill all the proccesses (or do whatever you want with this pidarr and after kill all the threads), like this example

    #include <stdio.h>
    #include <unistd.h>
    #include <sys/time.h>
    #include <signal.h>
    
    // maybe there is a standard macro or something like that
    // but on my machine in /proc/sys/kernel/pid_max there is 4194304
    #define PID_MAX 4194304
    
    pid_t pidarr[PID_MAX];
    
    static void
    sigalrmHandler(int sig)
    {
      for(int i = 1; i <= PID_MAX; i++){
        printf("Killing %ld\n",(long)pidarr[i]);
        kill(pidarr[i],SIGKILL);
      }
    }
    
    int main(void){
      struct sigaction sa;
      struct itimerval new_timer;
    
      pidarr[0] = getpid();
    
      sigemptyset(&sa.sa_mask);
      sa.sa_flags = 0;
      sa.sa_handler = sigalrmHandler;
      if(sigaction(SIGALRM,&sa,NULL) == -1){
        perror("setting the handler");
        return 1;
      }
    
      new_timer.it_value.tv_sec = 2;
      new_timer.it_value.tv_usec = 0;
      new_timer.it_interval.tv_sec = 0;
      new_timer.it_interval.tv_usec = 0;
    
      // Create the timer
      if(setitimer(ITIMER_REAL,&new_timer,NULL) == -1){
        perror("setting the timer");
        return 1;
      }
    
      for(int i = 1; ;i++){
        switch(pidarr[i] = fork()){
        case -1: // ERROR
          perror("setting the timer");
          return 1;
        case 0:
          for(;;) // Waiting to die
            ;
        case 1:
          wait(NULL);
          break;
        }
      }
    
      return 0;
    }
    

    I used settimer() (https://www.man7.org/linux/man-pages/man3/setitimer.3p.html) for create a two second timer and sigaction() (https://www.man7.org/linux/man-pages/man2/sigaction.2.html) for cast the signal, when the signal is arrived i will kill all the processes into the pidarr array, so my machine will not crush, if the timer was bigger we would have encountered the same problem, because the machine would crash before reaching the timer