0

I am experimenting with signals forking but I am not sure what is going on with my code. I should get 3 total processes. 1 parent 1 child and 1 grandchild. I decrement the level variable by 1 each time I make a fork so the program should terminate.

I don't understand why the program isn't generating any child processes. When I do ps aux| grep selfCaller I only ever see 1 process being run at a time.

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

const int   TEXT_LEN    = 16;

const int   NUM_SECS_TO_RUN = 30;

#define     PROGNAME    "selfCaller"


int     numTimesCalled[3]
                = {0,0,0};

pid_t       pidToSignal = -1;

pid_t       childPid    = -1;

int     level       = +2;

int     shouldRun   = 1;

void sigAlarmHandler(int sig){

    printf("Process %d: called level 0\n",level);
    int w = rand() % 10 + 1;
    alarm(w);
    numTimesCalled[0]++;
    if(level != 2){
        pid_t pid = getppid();
        kill(SIGUSR1, pid);
    }

}
void sigUs1Handler(int sig){
    printf("Process %d: called level 1\n",level);
    numTimesCalled[1]++;
    if(level != 2){
        pid_t pid = getppid();
        kill(SIGUSR2, pid);
    }

}
void sigUs2Handler(int sig){
    printf("Process %d: called level 2\n",level);
    numTimesCalled[2]++;

}
void sigIntHandler(int sig){
    shouldRun = 0;
}

int     main        (int        argc,
                 char*      argv[]
                )
{
    int comm;
  if (argc > 1){
  comm = strtol(argv[1], NULL, 0);
  }
  if (comm == 0 || comm == 1){
      level = comm;
  }
  srand(getpid());
  struct sigaction act;
  memset(&act, '\0', sizeof(act));


  act.sa_handler = sigAlarmHandler;
  sigaction(SIGALRM, &act, NULL);

  act.sa_handler = sigAlarmHandler;
  sigaction(SIGUSR1, &act, NULL);

  act.sa_handler = sigUs1Handler;
  sigaction(SIGUSR2, &act, NULL);

  act.sa_handler = sigIntHandler;
  sigaction(SIGINT, &act, NULL);
//   alarm(0);

  pid_t pi;
  if(level > 0){
    pi = fork();
  }
  printf("pid is %d", pi);
  if (pi ==-1){
      exit(EXIT_FAILURE);
  }
 char   text[TEXT_LEN];

  if(pi == 0){
      printf("This is the child");
      int r;
    snprintf(text,TEXT_LEN,"%d",level-1);
      r =execl(PROGNAME, text, NULL);
      if (r==-1){
          fprintf(stderr,"Cannot find %s\n",PROGNAME);
           exit(EXIT_FAILURE);
      }
  }

 if  (level == 2)
{
  int       i;

  for  (i = 0;  i < NUM_SECS_TO_RUN;  i++)
  {
    sleep(1);
  }
}
else
{
  pidToSignal   = getppid();

  while  (shouldRun)
  {
    sleep(1);
  }
}





  printf("Level %d: %d %d %d\n",level,
     numTimesCalled[0],numTimesCalled[1],numTimesCalled[2]
    );

  return(EXIT_SUCCESS);  
}
Mattreex
  • 189
  • 2
  • 17
  • 1
    Your coding style doesn't make me want to look at what your code really does. It is erratically laid out and not in any recognizable (and consistent) [indentation style](https://en.wikipedia.org/wiki/Indentation_style). I recommend using either Allman (which is what I use) or the 1TBS style (there are several closely related variants; it doesn't matter which you use as long as you're consistent about it). Strictly, you should [Avoid calling `printf()` in a signal handler](https://stackoverflow.com/q/16891019/15168) too. – Jonathan Leffler May 04 '20 at 06:21
  • You never use the `sigUs2handler()` function — I'm not sure how much that matters. Variable `comm` can be used uninitialized. Variable `pi` can be used uninitialized. You have `r = execl(PROGNAME, text, NULL);` — you should have `execl(PROGNAME, PROGNAME, text, NULL);`. There's no need to check the return value from the `exec*()` family of functions. If they return, they failed; if they succeed, they do not return. And you need to specify the executable name (`PROGNAME`), and also its argument list (so `argv[0]` should be `PROGNAME` again, and then `argv[1]` will be the level number, etc). – Jonathan Leffler May 04 '20 at 06:34

0 Answers0