Reputation: 471
Attempting to learn C forking. It correctly prints the number of times the main loop is suppose to run and the right number of threads but the execution time is off and the program never terminates. Am I making an infinite amount of processes?
After some suggestions here is a cleaner version of the code. The old version is located below. The updated part is still creating to many child processes and never exiting. I'm just not seeing what's going wrong.
Update: Suggestion by John Hascall fixed a formatting and threads running out of order. An infinite number of threads are still generated but now in the correct order. I.e prints thread execution time 1, 2, 3, 4... etc. Don't think the problem is the wait syscall but going to study it and see if I can't find anything.
Update**: I found the solution. The first problem I believe was that I didn't have a wait command and the second is that when putting in the wait I accidentally removed the check for count < argv[1]. I put it back in and it seems to be running correctly! Thanks for the help and style pointers everyone! Working version is below.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "./processes.h"
int main(int argc, char** argv) {
if (argc != 4) {
printf("Wrong number of arguments entered. Usage: #processes sleepTime inputFile.\n");
return 1;
}
if(atoi(argv[1]) <= 0){
printf("Incorrect number of children, must be greater than 0");
return -1;
}
int count = 0;
int index;
Child *child = malloc(sizeof(Child) * atoi(argv[1]));
int childIndex;
int pid;
do{
switch (pid = fork()){
case -1:
printf("Fork failed\n");
exit(1);
case 0:
sleep(atoi(argv[2]) * childIndex);
gettimeofday(&child[childIndex].endTime, NULL);
double elapsed = child[childIndex].endTime.tv_usec - child[childIndex].startTime.tv_usec;
printf("Time for process %d = %f microseconds\n", childIndex, elapsed);
break;
default:
childIndex = count + 1;
gettimeofday(&child[count].startTime, NULL);
child[count].index = count + 1;
child[count].pid = pid;
count++;
}
} while((wait(NULL) != -1) && (count < atoi(argv[1])));
return 1;
}
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "./processes.h"
int main(int argc, char** argv) {
if (argc != 4) {
printf("Wrong number of arguments entered. Try again.");
return 1;
}
if(atoi(argv[1]) <= 0){
printf("Incorrect number of children, must be greater than 0");
return -1;
}
int count;
int index;
Child *child = malloc(sizeof(Child) * atoi(argv[1]));
int pid = 1;
int childIndex;
for (count = 0; count < atoi(argv[1]); count++) {
if (pid != 0) {
childIndex = count + 1;
gettimeofday(&child[count].startTime, NULL);
child[count].index = count + 1;
pid = fork();
if (pid != 0){
child[count].pid = pid;
printf("Main thread loop: %d\n", count);
printf("Child process: %d\n", getpid());
}
}
}
if (pid == 0) {
//this is the child process
sleep(atoi(argv[2]) * childIndex);
gettimeofday(&child[childIndex].endTime, NULL);
double elapsed = child[childIndex].endTime.tv_usec - child[childIndex].startTime.tv_usec;
printf("Time for process %d = %f microseconds\n", childIndex, elapsed);
//printf("This is thread %d reporting in.\n", childIndex);
}
// printf("Testing\n");
return 1;
}
Upvotes: 4
Views: 2969
Reputation: 9416
The bigest issue is your child's code:
if (pid == 0) {
....
}
belongs in the same loop (say right after) the parent's code:
if (pid != 0) {
....
}
Also, you never check for pid == -1
(the fork()
failed).
A more standard way to write something like this is:
switch (pid = fork()) {
case -1:
/* handle fork error */
exit(1);
case 0:
/* child code goes here */
_exit(0);
default:
/* parent code goes here */
}
/* Also you probably want to look into the `wait()` syscall. */
do {} while (wait(NULL) != -1); /* <--- the very minimum */
Upvotes: 5