1. Not finding help here? Sign up for a free 30min tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Need help with lingering child process

  1. Jun 28, 2015 #1
    Hello,

    1. The problem statement, all variables and given/known data

    I am to implement a program where the parent process creates three child processes each running their own specific code, child 1 will be running a wallclock, child 2 will be a file manager and child 3 will be the countdown timer and is also the signaler. Child 1 is a basic wallClock which just outputs the current local time in military format. Child 2 is a file manager, therefore it creates it's own child process to run the exec command on the file "/usr/bin/uptime" and handles it's return to execute every 5 seconds or until it has been signaled. Child 3 is a basic countdown timer which upon reaching 00:00 it will signal the sibling processes to terminate.

    3. The attempt at a solution

    So far my implementation of the features have been correct, my only issue is with the runFile child. The output(given below the code) shows that when the countdown child process is done, it successfully signals the wallClock process to exit which it does successfully. However, after both child processes has closed, the runFile child is lingering for a couple more runs until it eventually receives the signal later. My question is why is that?, I don't get how it receives the signal MUCH later, because obviously the pipes are working because it eventually gets the signal and successfully terminates it self, so I don't understand why it receives the signal at a later time?

    Code (C):
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/wait.h>
    #include <sys/types.h>
    #include <time.h>

    #define DEFAULT 10
    #define pipeSize 2
    #define NUMBEROFCHILD 3
    #define STOP 1
    #define RUN 0

    int fd[pipeSize];
    int fd2[pipeSize];

    void wallClock(){
       int status = RUN;        /*signals*/
       int newStatus = RUN;

       time_t now;
       struct tm *lcltime;
       if(close(fd[1]) == -1){
          printf("Error closing writing end of pipe in wallClock\n");
          _exit(EXIT_FAILURE);
       }
     
       if(close(fd2[0]) == -1){                        /*close unused pipes*/
          printf("Error closing reading end of pipe2 in wallClock\n");
          _exit(EXIT_FAILURE);
       }
     
       if(close(fd2[1]) == -1){
          printf("Error closing writing end of pipe2 in wallClock\n");
          _exit(EXIT_FAILURE);
       }
     
       while(status != STOP){                                /*loop until signal occurs*/
          now = time(NULL);
          lcltime = localtime(&now);
          printf("the time is %d:%d:%d\n", lcltime->tm_hour,lcltime->tm_min,lcltime->tm_sec);
          sleep(1);
          read(fd[0], &newStatus, sizeof(newStatus));                    /*check for status*/
          status = newStatus;
       }
     
       if(close(fd[0]) == -1){
          printf("Error closing reading end of pipe\n");
          _exit(EXIT_FAILURE);
       }

       printf("Message has been received in wallClock()--Terminating now\n");
       _exit(EXIT_SUCCESS);
    }

    void runFile(){
       int status = RUN;
       int newStatus;
       pid_t pid;

       if(close(fd[1]) == -1){                            /*close all unused pipes*/
          printf("Error closing writing end of pipe runFile\n");
          _exit(EXIT_FAILURE);
       }
     
       if(close(fd[0]) == -1){
          printf("Error closing reading end of pipe runFile\n");
          _exit(EXIT_FAILURE);
       }
     
       if(close(fd2[1]) == -1){
          printf("Error closing writing end of pipe2 in runFile\n");
          _exit(EXIT_FAILURE);
       }
       while(status != STOP){                        /* wait until signal occurs */
          if((pid = fork()) == -1){                        /*create fork within child process to run exec */
             printf("Fork failed\n");
         _exit(EXIT_FAILURE);
          }
          else if(pid == 0){
         execl("/usr/bin/uptime", "uptime", NULL);
             printf("exec failed!\n");
         _exit(EXIT_FAILURE);
          }
          else{                            /*parent handler*/
             int ret;    
         pid_t justLeft;
         justLeft = wait(&ret);
         read(fd2[0], &newStatus, sizeof(newStatus));
             status = newStatus;
          }
          sleep(5);  
       }
     
       printf("Signal has been received, closing pipes and exiting uptime mananger\n");
     
       if(close(fd2[0]) == -1){
          printf("Error closing reading end of runFile pipe\n");
          _exit(EXIT_FAILURE);
       }
     
       _exit(EXIT_SUCCESS);
     
    }

    void countDown(int start){
       int stopNow = STOP;         /*signals*/
       int cont = RUN;
     
       if(close(fd[0]) == -1){                         /*close all unused pipes*/
          printf("Error closing reading end of pipe in countDown\n");
          _exit(EXIT_FAILURE);
       }
     
       if(close(fd2[0]) == -1){
          printf("Error closing reading end of pipe2 in countDown\n");
          _exit(EXIT_FAILURE);
       }
     
       while(start > 0){                /*while loop until start reaches 0*/
          if(start >= 10){
          printf("Count Down: 00:%2d\n", start);
          }
          else{
          printf("Count Down: 00:0%d\n", start);
          }
          write(fd[1], &cont, sizeof(cont));    /*write in pipe to continue still*/
          write(fd2[1], &cont, sizeof(cont));
          start--;
          sleep(1);
       }
     
       printf("Count Down: 00:00 -- sending message to terminate other processess\n");
       write(fd[1], &stopNow, sizeof(stopNow));     /*Tell others to terminate*/
       write(fd2[1], &stopNow, sizeof(stopNow));
     
       if(close(fd[1]) == -1){
          printf("Error closing writing end of pipe in countDown\n");
          _exit(EXIT_FAILURE);
       }
     
       if(close(fd2[1]) == -1){
         printf("Error closing writing end of pipe2 in countDown\n");
         _exit(EXIT_FAILURE);
       }
     
       _exit(EXIT_SUCCESS);
    }

    int main(int argc, char *argv[]){
     
       int time , i, status, newStatus, ret, n, newChild, numExited;
       pid_t child[NUMBEROFCHILD];
       pid_t pid;

       if(argc <= 2){            /*check arguments*/
          if(argv[1] != '\0'){
             time = atoi(argv[1]);
          }
          else
             time = DEFAULT;
       }
       else{
          printf("Too many parameters -- exiting program\n");
          return -1;
       }
     
       if(pipe(fd) == -1){            /*open pipes*/
          printf("Error opening pipe\n");
          exit(EXIT_FAILURE);
       }
     
       if(pipe(fd2) == -1){
          printf("Error opening pipe\n");
          exit(EXIT_FAILURE);
       }
     
       for(i = 0; i < NUMBEROFCHILD; i++){       /* create children */  
          if((child[i] = fork())  == -1){
             printf("Error in creating child\n");
         exit(EXIT_FAILURE);
          }
          if(child[i] == 0){
             switch(i){
            case 0:   wallClock();
            break;
            case 1:   runFile();
            break;
            case 2:   countDown(time);
            break;
         }
          }
       }
     
         
       if(close(fd[1]) == -1){          
          printf("Error closing parent reading pipe\n");
          exit(EXIT_FAILURE);
       }
     
       if(close(fd[0]) == -1){          
          printf("Error closing parent writing pipe\n");
          exit(EXIT_FAILURE);
       }
     
       if(close(fd2[1]) == -1){          
          printf("Error closing parent reading pipe2\n");
          exit(EXIT_FAILURE);
       }
     
       if(close(fd2[0]) == -1){          
          printf("Error closing parent writing pipe2\n");
          exit(EXIT_FAILURE);
       }
     
       n = NUMBEROFCHILD;
       while(n > 0){            /*Wait for all children to finish*/
          pid = wait(&status);
             if(pid == -1){
            printf("Error exiting with childPID %d\n", pid);
            exit(EXIT_FAILURE);
         }
        --n;
        printf("Child %d has exited successfully\n", pid);
       }
     
       printf("All processes has ended, exiting program --\n");
       return 0;
     
    }
     
    Code (C):
    > gcc -g assign3.c
    > a.out 15
    Count Down: 00:15
    the time is 18:5:25
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.48, 3.78, 4.80
    Count Down: 00:14
    the time is 18:5:26
    Count Down: 00:13
    the time is 18:5:27
    Count Down: 00:12
    the time is 18:5:28
    Count Down: 00:11
    the time is 18:5:29
    Count Down: 00:10
    the time is 18:5:30
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.46, 3.77, 4.79
    the time is 18:5:31
    Count Down: 00:09
    the time is 18:5:32
    Count Down: 00:08
    the time is 18:5:33
    Count Down: 00:07
    Count Down: 00:06
    the time is 18:5:34
    Count Down: 00:05
    the time is 18:5:35
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.45, 3.76, 4.79
    Count Down: 00:04
    the time is 18:5:36
    the time is 18:5:37
    Count Down: 00:03
    Count Down: 00:02
    the time is 18:5:38
    the time is 18:5:39
    Count Down: 00:01
    the time is 18:5:40
    Count Down: 00:00 -- sending message to terminate other processess
    Child 9779 has exited successfully
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.44, 3.75, 4.77
    Message has been received in wallClock()--Terminating now
    Child 9777 has exited successfully
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.42, 3.74, 4.77
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.40, 3.73, 4.76
      6:05pm  up 279 day(s),  8:52,  27 users,  load average: 3.39, 3.72, 4.75
      6:06pm  up 279 day(s),  8:52,  27 users,  load average: 3.38, 3.71, 4.74
      6:06pm  up 279 day(s),  8:53,  27 users,  load average: 3.36, 3.71, 4.73
      6:06pm  up 279 day(s),  8:53,  26 users,  load average: 3.37, 3.70, 4.73
      6:06pm  up 279 day(s),  8:53,  26 users,  load average: 3.46, 3.71, 4.72
      6:06pm  up 279 day(s),  8:53,  26 users,  load average: 3.87, 3.80, 4.75
      6:06pm  up 279 day(s),  8:53,  26 users,  load average: 4.59, 3.95, 4.79
      6:06pm  up 279 day(s),  8:53,  27 users,  load average: 5.29, 4.10, 4.84
      6:06pm  up 279 day(s),  8:53,  27 users,  load average: 5.84, 4.23, 4.88
      6:06pm  up 279 day(s),  8:53,  27 users,  load average: 6.36, 4.37, 4.92
    Signal has been received, closing pipes and exiting uptime mananger
    Child 9778 has exited successfully
    All processes has ended, exiting program --
     
     
  2. jcsd
  3. Jun 29, 2015 #2
    I think I see your problem.
    A quick caveat though, whenever working on this sort of task I always used pThreads instead of pipes & forks.

    Let me ask you a couple questions to maybe help point you in the right direction.

    If you were to describe someone what data structure a pipe is most like what would you use? A variable, an array, a stack etc?
    Does the number of extra runs stay the same? or does it vary? What if you change to countdown time? Does it stay the same or vary?

    Hope this gets you heading the right direction.


    A couple other things. Good job on the coding style, you should however try and get away from ALL magic numbers.
    For example which is easier to understand if you haven't looked at the code before
    This:
    Code (Text):
     if(close(fd2[0]) == -1){
    or
    Code (Text):
    #define THREAD0  0
    #define FAIL   -1

    ......

    if(close(fd2[THREAD0]) == FAIL){
     
  4. Jun 29, 2015 #3
    If I were to describe what data structure I pipe is I would say it would be an array in which the contents of a certain index points to either where stdout and stdin is or used to be?

    The number of extra runs seem to be consistent in the amount, and I also did notice it changes when I change the amount of time I put the program to sleep(), when you say if I change to countdown time, do you mean instead of it doing sleep(), I should just make the countdown timer signal that process to exec every time after 5 seconds has passed through?

    I think that's one solution but is that where you were getting at?
     
  5. Jun 29, 2015 #4
    Its been a while since I covered Pipes in OS class but I believe the memory is copied. But that isn't relevant. You're on the right track. An array is a good way to think about it. Ask how stuff is put into and taken out of the array.

    I stumbled upon your issue when I was trying to understand the code. One the things I checked was to examine
    Code (Text):
         read(fd2[0], &newStatus, sizeof(newStatus));
             status = newStatus;
    What newStatus' value was. Maybe take a look at that?
     
  6. Jun 29, 2015 #5
    newStatus value is 0 every run like it's suppose to, when the signal is sent the other 2 processes terminate but this process lingers for exactly 12 runs until eventually the newStatus becomes 1 which means it received the signal then it terminates itself.

    As for how stuff being taken out of the array or the pipe, I feel that the way it works is when the countdown process does a write function on the pipe it means that the contents that is passed through the parameters will be located on the writing end of the pipe and when I do the read, I take the contents at pipe[0] out and put it at the address where I want it. Unless something is over-writing the pipe so the process doesn't get the signal until later?
     
  7. Jun 29, 2015 #6
    So ask how was the process able to pull out 12 extra 0's? Did they just magically appear? Or was your code putting them there?

    Do you need to explicitly send a "Keep running" message? or can you use the return value of read (it returns the number of bytes read) to get around this??
     
  8. Jul 4, 2015 #7
    I'm more of an experimentalist, so I tend to add a lot of debugging code to fix problems like this one.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Need help with lingering child process
  1. Signal processing help (Replies: 2)

  2. Signal Processing help (Replies: 1)

Loading...