Thanks to Adam Powers for the framework used for this demo program


#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <signal.h>

/* see http://www.dinkumware.com/htm_cl/signal.html  for more on
 *  signal handling
 */

#define DEFAULT_ITERS     10
#define DEFAULT_NUM_PROCS 10

#define DEBUG

#ifdef DEBUG
   #define debugf(fmt, arg...) {fprintf (stdout, fmt, ##arg);}
#else /* not DEBUG */
   #define debugf(fmt, arg...) {}
#endif /* DEBUG */

#define errorf(fmt, arg...) fprintf (stdout, fmt, ##arg)


/* Forward Definition
 */
void child_body(long iters);
void sig_handler(int signal);
void core_dump(int signal);

int main(int argc, char *argv[])
{
   /* Number of iterations a child will do
    */
   long iters = DEFAULT_ITERS;

   /* Number of child processes we'll create
    */
   int num_procs = DEFAULT_NUM_PROCS;
   int i;
   int errors = 0;
   int pid, status;

   double total_time;
   struct timeval start, end;

   /* setup signal handlers
    */
   signal (SIGUSR2, sig_handler);
   signal (SIGSEGV, core_dump);

   /* check the command line arguments
    */
   if (argc >= 2)
   {  num_procs = atoi(argv[1]);
      iters = atol(argv[2]);
   }
   else
   {  printf("Usage: multiproc [# processes] [# iterations]\n");
   }
   printf("Doing %i processes, %i iterations each\n", num_procs, iters);

   /* start the timer
    */
   gettimeofday(&start, NULL);

   /* branch off child processes
    */
   for (i=0; i<num_procs; ++i)
   {  pid = fork();

   /* Am I the child?
    */
      if (pid == 0)
      {  child_body(iters);
         return 0;
      }
   }

   /* wait for each child to return
    */
   for (i=0; i<num_procs; ++i)
   {  pid = wait(&status);
      errors += (status >> 8);
      if (errors)
      {
      /* signal all our children
       */
         errorf ("*** ERROR - killing children ***\n");
         printf("child %d returned status=%d\n", pid, status);
         killpg (getpgrp(), SIGUSR2);
      }
   }

   /* stop the timer
    */
   gettimeofday(&end, NULL);

   total_time =
      (end.tv_sec   +   (end.tv_usec * 0.000001)) -
      (start.tv_sec +   (start.tv_usec * 0.000001));

   printf("\nResults\n");
   printf("-------\n");
   printf("Number of children:   %d\n", num_procs);
   printf("Iterations per child: %d\n", iters);
   printf("Total iterations:     %d\n", iters*num_procs);
   printf("Total time for test:  %f\n", total_time);
   printf("Time / iteration:     %f\n",
      total_time / (double) (num_procs * iters));

   return 0;
}


void sig_handler (int signal)
{
   if (signal != SIGUSR2)
   {
      errorf ("sig handler got signal %d, ignored\n", signal);
   }
   exit (1);
}

void core_dump (int signal)
{
   errorf ("child %d died!\n", getpid());
   exit (1);
}

void child_body(long iters)
{
   long i;

   /* If an error code other than '0' is returned, we
    *  indicate an error happened and the parent process
    *  will kill all the children
    */
   int errorCode = 0;
   debugf ("%d is in process group %d\n", getpid(), getpgid (0));

   for (i=0; i < iters; ++i)
   {
      /* do the iteration body here
       */
   }
   exit(errorCode);
}


Alternate code for wait

        bool done = false;
        int status;
        while(!done)
        {   cout << "wait start" << endl;
            // wait with WNOHANG as last arg to not block
            pid_t child_pid = waitpid(-1, &status, 0);
            if (child_pid > 0)
            {   if (WIFEXITED(status))
                {   cout << "child " << child_pid <<
                            " terminated normally" << endl;
                }
                if (WCOREDUMP(status))
                {   cout << "child " << child_pid <<
                           " core dumped" << endl;
                }
                if (WIFSIGNALED(status))
                {   cout << "child " << child_pid <<
                        " terminated from uncaught signal" <<
                        WTERMSIG(status) << endl;
                }
                if (WIFSIGNALED(status))
                done = true;
            }
            else if (child_pid < 0)
            {   cout << "some kind of error happened during 'waitpid'"
                     << endl;
                done = true;
            }
        }
-- MattWalsh - 02 Jan 2002
Topic revision: r2 - 08 Mar 2006 - MattWalsh
 
This site is powered by the TWiki collaboration platformCopyright © 2008-2012 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback