Search code examples
c++fork

Trying to create multiple processes in C++ using fork(); doesn't appear to be working


I'm trying to create a parent process with multiple child processes using fork() in C++. I tried using the code from this question to create a simple program that would have each process count upwards; the parent would print "I am process 0", the first child "I am process 1", and so on.

#include <unistd.h>
#include <stdio.h>
#include <fstream>
#include <sys/wait.h>
using namespace std;

const int PROCESSES = 5;
void Printer(int psno);
int iAmProcess = 0;

int main()
{

    int pids[PROCESSES];

    Printer(iAmProcess);

    for (int j = 0; j < PROCESSES; j++)
    {
        if (pids[j] = fork() < 0)
        {
            perror("Error in forking.\n");
            exit(EXIT_FAILURE);
        }
        else if (pids[j] == 0)
        {
            Printer(iAmProcess);
            exit(0);
        }
    }

    int status;
    int pid;
    int n = PROCESSES;
    while (n > 0)
    {
        pid= wait(&status);
        --n;
    }
    return 0;
}

void Printer(int psno)
{
    printf("I am process %d\n", psno);
}

Instead of the expected output:

I am process 0
I am process 1
I am process 2
I am process 3
I am process 4
I am process 5

I get:

I am process 0
I am process 0
I am process 0
I am process 0

And then the program terminates. What am I doing wrong?


Solution

  • What am I doing wrong?

    One thing that you're doing wrong is on this line:

        if (pids[j] = fork() < 0)
    

    Due to the order-of-operations/precedence rules in C++, that line is being interpreted by the compiler as:

        if (pids[j] = (fork() < 0))
    

    ... which is to say, pids[j] is being set to true (aka 1) if fork() returns a negative value, or to false (aka 0) otherwise. That's probably not what you intended. What you want to write instead is:

        if ((pids[j] = fork()) < 0)
    

    ... so that pids[j] will be set to the return value of fork(), and then that value will be tested to see if it less than zero. (I always use explicit parentheses in this sort of situation, specifically because I can never quite remember the operator-precedence rules, and placing explicit parentheses means I [and the code's future readers] don't have to remember them)

    With that change (and the addition of the iAmProcess = j+1; line that you mentioned in your comment, to the top of of the for-loop -- feel free to edit your post to update your code snippet, btw), I get this output from your program:

    $ ./a.out
    I am process 0
    I am process 2
    I am process 1
    I am process 3
    I am process 4
    I am process 5
    

    ... which isn't exactly what you expected (the output isn't quite in order), but that's because the child processes you spawn all run asynchronously to each other and are not required to execute in any particular order relative to each other.