I'm reading lines of text from file, and for each line I'm processing it using several { fork() --> child process invokes execvp(), and parent invokes wait() } . at the end of process I'm writing the results to a file.
Problem is: the while loop seems to iterate too much and also the writing to the file.
The results.csv file contains 6 lines instead of just 2 (the while iteration iterates a text file with 2 lines, but also when I use printf it seems like the last line is read twice).
What am I missing here?
The code example is:
FILE* results = fopen("results.csv", "w");
if (results == NULL){
fclose(fp);
perror("Failed opening results file");
exit(-1);
}
fdIn = open(inputPath, O_RDONLY);
if (fdIn < 0){
perror("Failed opening input file");
exit(-1);
}
while (fgets(student, sizeof(student), fp) != NULL) {
// override end line char of unix ('\n') with '\0'
student[strlen(student)-1] ='\0';
pid = fork();
if (pid < 0){
close(fdIn);
perror("Failed creating process for executing student's program");
exit(-1);
}
if (pid == 0) {// son process code
fdOut = open("tempOutput.txt", (O_WRONLY | O_CREAT | O_TRUNC), 0666);
if (fdOut < 0){
perror("Failed opening temporary output file");
exit(-1);
}
close(1);
dup(fdOut);
close(fdOut);
close(0);
dup(fdIn);
close(fdIn);
char studProgPath[bufSize];
strcpy(studProgPath,studentsFolderPath);
strcat(studProgPath,"/");
strcat(studProgPath,student);
strcat(studProgPath,"/");
strcat(studProgPath,"a.out");
char * args[] = {"a.out", NULL};
ret_code = execvp(studProgPath,args);
if (ret_code == -1){
perror("Failed executing student program");
exit(-1);
}
}
waited = wait(&stat);
if (stat == -1){ // need to grade 0
printf("%s,0\n",student);
}else{ // open process to compare the output with the expected
pid = fork();
if (pid < 0){
perror("Failed opening process for comparing outputs");
exit(-1);
}
if(pid == 0) { // son process
char * args[] = {"comp.exe",outputPath,"tempOutput.txt",NULL};
ret_code = execvp("comp.exe",args);
exit(ret_code);
}
waited = wait(&stat);
if (stat == -1) {
perror("Failed executing comparing program");
exit(-1);
} else if (stat == 0 || stat == 1) { // if outputs are not the same
fprintf(results,"%s,0\n",student);
} else { // matching outputs grade 100
fprintf(results,"%s,100, pid: %d\n",student,getpid());
}
}
}
execvp()(or any otherexec*()function). If the function is successful, it does not return; if it returns, it failed.a.outprogram do with its standard input? It's a bit surprising that you redirect the file input to the standard input of what becomes thea.outprocess. You don't print an error if thecomp.exeprocess fails. Until you know what's wrong, that should be printed — and probably even after you know what's up.