0

I need to create a program that creates n number of processes and displays information. When each process ends, I am to print it's PID and the exit status. The way I am doing it, the parent program waits to create the next process until the current one ends. I need it so that it keeps creating the child processes and just displays the exit information when ever one process ends without blocking the parent from continuing. I can;t figure out where to put my wait to ensure this. Below is my code:

int main (int argc, char *argv[])
{
  if (argc < 2)
  {
     printf("\n\nUsage: %s <enter a number (12 or less)>\n\n", argv[0]);
     exit (-1);
  }
  else
  {
    int *processNum = (int *)malloc(sizeof(12));
    int processNumTemp;

    processNumTemp = atoi(argv[1]);
    processNum = &processNumTemp;

  if(*processNum > 12 || *processNum < 1)
    {
      printf("\n\nUsage: %s <enter a number (12 or lrss)>\n\n", argv[0]);
    }
  else
    {
      parentInfo(processNum);
      createChildProcess(processNum);
    }


  }

 return 0;
}


//Name:  parentInfo
//Description:  Displays information about the parent process
//Parameters:  processNum - stores the number of child processes to create
//             (entered at the command line).
//Return:  none
void parentInfo(int *processNum)
{
 printf("Parent process ID:  %d\n", getppid());
 printf("Number of processes to create:  %d\n", *processNum);
}


//Name:  createChildProcess
//Description:  Creates n number of child processes.
//              For each child process, it says its a child process and it
//              displays its PID.
//              After each child process closes, the parent displays info.
//Parameters:  processNum - stores the number of child processes to create
//             (entered at the command line).
//Return:  none
void createChildProcess(int *processNum)
{
 int i;
 int childStatus;
 pid_t childpid;

 /*The for loop will create n number of processes based on the value of            processNum.*/
 for(i = 1; i <= *processNum; i++)
 childpid = fork();

  //Executes if fork didn't work
  if(childpid < 0)
    {
      perror("fork");
      exit(1);
    }

  //Executes if the fork worked
  else if( childpid == 0)
    {
      int pid = getpid();

      //Prints a message and the child processe's PID
      printf("\nHello I am a child process.\n");
      printf("My PID is %d. \n", getpid());

      for(int x = 1; x <= pid; x ++);

      exit(15);
    }

}
      //Executes after the child process has ended
      //Checks the child process's exit status

      waitpid(childpid, &childStatus, WUNTRACED);
      printf("\nPID of the child process that was just created:  %d.\n", childpid);

      if(WIFEXITED(childStatus))
        {
          printf("PID %d exited normally.  Exit number:  %d\n", childpid, WEXITSTATUS(childStatus));
        }
      else if(WIFSTOPPED(childStatus))
        {
          printf("PID %d was stopped by %d\n", childpid, WSTOPSIG(childStatus));
        }
      else if(WIFSIGNALED(childStatus))
        {
          printf("PID %d exited due to signal %d\n.", childpid, WTERMSIG(childStatus));
        }
      else
        {
          perror("waitpid");
        }
}
ValenceElectron
  • 2,678
  • 6
  • 26
  • 27
Stc5097
  • 291
  • 1
  • 11
  • 25

3 Answers3

3

Before fork code

signal(SIGCHLD, childHandler);

In childHandler put your waitpid code.

void childHandler(int signum)
{

    pid_t childpid;
    int childstatus;

    while ((childpid = waitpid( -1, &childstatus, WNOHANG)) > 0)
    {
        if (WIFEXITED(childStatus))
        {
            printf("PID %d exited normally.  Exit number:  %d\n", childpid, WEXITSTATUS(childStatus));
        }
        else
            if (WIFSTOPPED(childStatus))
            {
                printf("PID %d was stopped by %d\n", childpid, WSTOPSIG(childStatus));
            }
            else
                if (WIFSIGNALED(childStatus))
                {
                    printf("PID %d exited due to signal %d\n.", childpid, WTERMSIG(childStatus));
                }
                else
                {
                    perror("waitpid");
                }
        }
    }
}

You should not use async-unsafe calls like printf inside a signal handler so alter your code to save the status in a global or heap allocated array - you know the size to create from processNum - and print the status info outside the handler.

Also, as currently structured, your parent could end before reaping all the children. Add a counter for the children so that you wait on all of them before the parent exits.

Duck
  • 26,924
  • 5
  • 64
  • 92
0

Look into signal SIGCHLD. If you have it blocked, you must unblock it or might instead explicitly check for it.

Deduplicator
  • 44,692
  • 7
  • 66
  • 118
  • What's a detached child? – Duck Apr 08 '14 at 14:16
  • See Stackoverflow post [Detached vs. Joinable POSIX threads](http://stackoverflow.com/questions/3756882/detached-vs-joinable-posix-threads). THe only important thing in this case is they are not detached. – Deduplicator Apr 08 '14 at 14:21
  • OP is creating processes not threads. This is irrelevant. Apples and oranges. – Duck Apr 08 '14 at 14:22
0

The purpose of wait is to, well, wait, so the way to solve your problem is to first create all the children, then start waiting for them to terminate. Here is a program which does that:

// fork
#include <unistd.h>

// wait
#include <sys/types.h>
#include <sys/wait.h>

// exit
#include <stdlib.h>

//printf
#include <stdio.h>

void child( int id)
{
  int seed= id;
  int x= rand_r( &seed) % 10;
  sleep( x);

  exit( x);
}

int main( int argc, char *argv[])
{
  const int n= 5;
  int i;

  printf( "creating %d children.\n", n);
  for ( i= 0; i < n; ++i) {
    pid_t pid= fork();
    if ( !pid)
      child( i); // does not return
    else
      printf( "child [0x%x] created.\n", pid);
  }

  // all the children are created now
  // now we wait for them to terminate

  printf( "waiting for children to terminate.\n", n);
  for ( i= 0; i < n; ++i) {
    int result;
    pid_t pid= wait( &result);
    printf( "child [0x%x] terminated with result [%u].\n", pid, WEXITSTATUS( result));
  }

  puts( "all children terminated.");
}
xxa
  • 1,258
  • 9
  • 20