I'm studying how fork() actually works so my code below has no purpose other than spawning new processes with fork() and see them die randomly. So:
<<< >>>
.So, can anyone help me understand my 1st point, and identify why 2 is happening?
Full code below:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <string.h>
const int PASS = 5;
const int RANDLIMIT = 5;
const int FORKNUMBER = 2;
int i = 0;
void doSomeWork(char *who);
int main(int argc, char *argv[])
{
printf("Just started, I am: %d\n", (int) getpid());
int j;
pid_t pid;
for (j=0; j < FORKNUMBER; j++)
pid = fork();
printf("fork returned: %d\n", (int) pid);
srand((int) pid + rand());
if (pid < 0) {
perror("fork failed");
} else if (pid == 0) {
char * childPid;
char * childName;
sprintf(childPid, "%d", (int) getpid());
childName = (char *) malloc(strlen("Child - ") + strlen(childPid) + 1 );
strcpy(childName, "Child - ");
strcat(childName, childPid);
doSomeWork(childName);
exit(0);
}
//<<< The malloc above for the child to send a parameter >>>
//<<< to the function, works fine. But when I try to do >>>
//<<< the same for my parent, the simple declaration of a>>>
//<<< char below, makes the child block (the if PID==0) >>>
//<<< not run. The 3 lines commented below were an >>>
//<<< attempt to understand what was preventing the child>>>
//<<< block from running. Now, if the parent calls the >>>
//<<< function with a string not declared before, the >>>
//<<< child block runs fine.>>>
//char parentName[strlen("Parent") + 1];
//strcpy(parentName, "Parent");
//doSomeWork(parentName);
doSomeWork("Parent");
//wait(NULL);
return(0);
}
void doSomeWork(char *who)
{
int control = 0;
for(; i < PASS; i++){
sleep(rand() % RANDLIMIT);
printf("%s: Done pass #%d, my parent = %d\n", who, i, getppid());
if (control == 0)
{
char childWord[6];
strncpy(childWord, who, 5);
if (strcmp(childWord, "Child") == 0 && (int) getppid() == 1 )
{
control = 1;
printf("%s: became orphan at #%d\n", who, i);
}
}
}
printf("%s: exiting...\n", who);
}
EDIT:
For 1, I created a function like below:
int nbDigits(int number)
{
int i=0;
for(; number > 10; i++)
{
number /= 10;
}
return ++i;
}
Now instead of declaring a pointer to a char like this, char * childPid;
I declared a char array like this char childPid[nbDigits(getpid()) + 1];
and everything worked like a charm.
Check out Joseph's suggestion below using asprintf()
, seems neat.
fork()
in a loop but only check what it returns at the end of the loop if you want your program to work. When you do so, you're starting an exponential number of child processes, and each one thinks it's "the parent" as long as it was the parent of its final fork(). Move your test of pid
to inside the loop.char * childPid;
sprintf(childPid, /* ... */);
That's going to clobber some random memory. You need to point childPid
to something before you sprintf
to it, or replace sprintf
with something like asprintf
that will allocate itself.