1

I'd like to know if there is a way to pause a process but continue the program.

I need to create processes like this:
enter image description here

But when I hit P4 it ends, dies and then P2 creates P5. Then P2 Dies and P1 creates P3 and the same thing happens there.

I need to create the whole 'tree' before the processes start to die.
Can't use wait nor waitpid() because it only targets it's son.

Is there a way to Pause P4 and continue from it's father ?
If I can't how could I achieve my goal ?

My currently code: It's creating in this order:

P1 -> P2 -> P4 -> P4 DIES -> P5 -> P5 DIES -> P2 DIES -> P3 -> P6 -> P6 DIES -> P7 -> P7 DIES -> P3 DIES -> P1 DIES

    #include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h> 
#include <time.h>


int main(){
    clock_t t;
    double time_taken;
    t = clock();
    int status;
    pid_t idProcesso, pai;
    printf("P1 created: %d\n", getpid());

    idProcesso = fork();
    switch(idProcesso)
    {
        case -1: exit(1);

        case 0: //P2
            printf("P2 created: %d  -  son of P1: %d\n", getpid(), getppid());
            idProcesso = fork();
            switch(idProcesso)
            {
                case -1: exit(1);

                case 0: //P4
                    printf("P4 created: %d  -  son of P2: %d\n", getpid(), getppid());
                    sleep(1);
                    break;
                default://P2
                    idProcesso = fork();
                    switch(idProcesso)
                    {
                        case -1: exit(1);

                        case 0://P5
                            printf("P5 created: %d  -  son of P2: %d\n", getpid(), getppid());

                            break;
                        default://P2
                            sleep(1);
                            break;
                    }

                    break;
            }
            break;
        default:

            idProcesso = fork();
            switch(idProcesso)
            {
                case -1: exit(1);

                case 0://P3
                    printf("P3 created: %d  -  son of P1: %d\n", getpid(), getppid());
                    idProcesso = fork();
                    switch(idProcesso)
                    {
                        case -1: exit(1);

                        case 0://P6
                            printf("P6 created: %d  -  son of P3: %d\n", getpid(), getppid());
                            sleep(1);
                            break;  
                        default://P3
                            idProcesso = fork();
                            switch(idProcesso)
                            {
                                case -1: exit(1);

                                case 0://P7
                                    printf("P7 created: %d  -  son of P3: %d\n", getpid(), getppid());
                                    break;
                                default://P3

                                    break;
                            }
                            sleep(1);
                        break;
                    }
                    break;

                default:
                    sleep(4);
                    break;
            }
            break;
    }



    printf("Process id: %d terminated\n", getpid());
    exit(0);
}
PlayHardGoPro
  • 2,791
  • 10
  • 51
  • 90
  • On recent linux you can re-parent processes: http://stackoverflow.com/questions/6476452/process-re-parenting-controlling-who-is-the-new-parent – Eugene Sh. Apr 29 '16 at 21:49
  • you need to have all 7 processes running at the same time, or building the tree serially, with roots/branches dying off as you go? p7 should be the last process standing? – Marc B Apr 29 '16 at 21:50
  • And.. why can't you just use some conventional synchronization mechanisms? Like pipes. – Eugene Sh. Apr 29 '16 at 21:51
  • @MarcB Yes, I need to create all of them just then kill them all. I can only create one side, kill it, then start creating the other side. Don't know how to create the right side and keep left side alive. – PlayHardGoPro Apr 29 '16 at 21:53
  • There is no reason for P2 to wait for P4 before creating P5. – jxh Apr 29 '16 at 21:56
  • Updated with my currently code. Maybe you guys can help me find my mistakes. Don't know what to try – PlayHardGoPro Apr 29 '16 at 22:01
  • Processes are independent of each other. You can "pause" a process with `sleep()` or `pause()`. – Crowman Apr 29 '16 at 22:13
  • @PaulGriffiths But doesn't the whole program stops ? I was making some tests with prints and that was what I understood. – PlayHardGoPro Apr 29 '16 at 22:16
  • @PlayHardGoPro: The process stops, yes, but that's what you are saying you want it to do. You want it to hang around until you've created all the rest of your processes. So this is your desired behavior. – Crowman Apr 29 '16 at 22:17

1 Answers1

1

Processes run independently of each other, so you just need to:

  1. Keep your child processes alive for long enough for all your processes to get created, which is easy enough to do using sleep(), for instance; and

  2. Don't start wait()ing for any of your child processes until you've created them all.

Here's an example:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>

int main(void)
{
    pid_t pids[8] = {0};
    printf("P1 created (%lu).\n", (unsigned long) getpid());

    for ( size_t i = 1; i < 3; ++i ) {
        pids[i] = fork();

        if ( pids[i] == -1 ) {
            perror("fork() error");
            exit(EXIT_FAILURE);
        }
        else if ( pids[i] == 0 ) {
            printf("P%zu created (%lu).\n", i + 1, (unsigned long) getpid());

            for ( size_t j = 1 + i * 2; j < 3 + i * 2; ++j ) {
                pids[j] = fork();

                if ( pids[j] == -1 ) {
                    perror("fork() error");
                    exit(EXIT_FAILURE);
                }
                else if ( pids[j] == 0 ) {
                    printf("P%zu created (%lu).\n", j + 1,
                            (unsigned long) getpid());
                    sleep(8 - j);
                    printf("P%zu exiting.\n", j + 1);
                    exit(EXIT_SUCCESS);
                }
            }

            for ( size_t j = 2 + i * 2; j >= 1 + i * 2; --j ) {
                if ( waitpid(pids[j], NULL, 0) == -1 ) {
                    perror("waitpid() error");
                    exit(EXIT_FAILURE);
                }
                printf("Waited for P%zu (%lu).\n", j + 1,
                        (unsigned long) pids[j]);
            }

            printf("P%zu exiting.\n", i + 1);
            exit(EXIT_SUCCESS);
        }
    }

    for ( size_t i = 2; i > 0; --i ) {
        if ( waitpid(pids[i], NULL, 0) == -1 ) {
            perror("waitpid() error");
            exit(EXIT_FAILURE);
        }
        printf("Waited for P%zu (%lu).\n", i + 1, (unsigned long) pids[i]);
    }

    printf("P1 exiting.\n");

    return 0;
}

with output:

paul@horus:~/src/sandbox$ ./procs
P1 created (27206).
P2 created (27207).
P3 created (27208).
P4 created (27209).
P5 created (27210).
P6 created (27211).
P7 created (27212).
P7 exiting.
Waited for P7 (27212).
P6 exiting.
Waited for P6 (27211).
P3 exiting.
Waited for P3 (27208).
P5 exiting.
Waited for P5 (27210).
P4 exiting.
Waited for P4 (27209).
P2 exiting.
Waited for P2 (27207).
P1 exiting.
paul@horus:~/src/sandbox$ 

Note that the order in which processes are run is inherently unpredictable, so each time you run it you could get slightly different results to the above. I have not attempted to make them create or exit in order, except for a half-hearted attempt at sleep() in the four leaf processes, which is otherwise just there to keep them all alive for long enough. You can almost guarantee the execution and termination order with strategic calls to sleep(), or guarantee it using some form of inter-process communication. As a general rule, you shouldn't care about this order, just about whether your actual work gets done in order.

But, it fulfills the criteria of keeping all the processes alive before any of them start to die.

Crowman
  • 25,242
  • 5
  • 48
  • 56
  • Thanks man. Compiling your code I got this: `P1(3808), P3(3810), P2(3809)` -> Diferent order but we can see it's ok because of the Pids. But now I have: `P6(3811) P4(3813) P7(3812) P5(3814)`. As the Pids are in diferent order, doesnt it mean that it is being created in a wrong order ? – PlayHardGoPro Apr 29 '16 at 23:35
  • 1
    @PlayHardGoPro: I refer you to this part of my answer: "Note that the order in which processes are run is inherently unpredictable". – Crowman Apr 29 '16 at 23:36
  • You rock ! Work perfect. But I could not understand the reason for those `for loop`. I updated my code and it's creating fine BUT processes are not dying in the right order. (child before parent). Could you take a quick look ? – PlayHardGoPro Apr 29 '16 at 23:51
  • 1
    The `for` loops are there because each parent process has to create two children. Practically any time you want to do something more than once, you'll want to use a loop to do it. – Crowman Apr 29 '16 at 23:53