I’m busy with an assignment but I’m stuck. I get errors and I don’t understand what I’m doing wrong.
So in the main I make three children. Between the first and second I have a pipe (pipe12). Between the second and the third I have a pipe (pipe23). Now when the first child (reader) is ready with reading, it closes pipe12, but read of the second child doesn’t get an EOF. Secondly when the second child wants to write to pipe23, the child crashes.
I guess I do something wrong in the initialization of the pipes, but what?
This is the parent
for(childnr=2; childnr>=0;childnr--)
{
tasks[childnr].pid=fork();
if(tasks[childnr].pid==-1)
{
printf("fork error\n");
exit(1);
}
else if(tasks[childnr].pid==0)
{
switch(childnr)
{
case 0:
close(pipe12[0]);
close(pipe23[0]);
close(pipe23[1]);
reader();
break;
case 1:
close(pipe12[1]);
close(pipe23[0]);
tokenizer();
break;
case 2:
close(pipe12[0]);
close(pipe12[1]);
close(pipe23[1]);
evaluator();
break;
default:
printf("childnr error\n"); //errorhandling
}
}
else
close(tasks[childnr].errorpipe[1]);
}
close(pipe12[0]);
close(pipe12[1]);
close(pipe23[0]);
close(pipe23[1]);
... continue with the parent
This is the first child:
void reader(void)
{
atexit(*reader_exit);
if((readfile = fopen(calculatorfile,"r"))==NULL)
{
printf("R send error to errorHandler"); //errpipe!
exit(0);
}
char line[50];
const char *valid_characters = "0123456789 +-/*\n";
while(fgets ( line, sizeof line, readfile ) != NULL)
{
printf("R reading ...%s",line);
char *c = line;
while(*c)
{
if(!strchr(valid_characters,*c))
{
printf("R invalid character: %c in %s",*c,line);
line[0]=0;
break;
}
c++;
}
write(pipe12[1],line,sizeof line);
}
exit(0);
}
void reader_exit(void)
{
printf("R reader exit\n");
fclose(readfile);
close(pipe12[1]);
close(tasks[childnr].errorpipe[1]);
}
And the second child:
void tokenizer(void)
{
atexit(*tokenizer_exit);
char buffer[50];
while(read(pipe12[0],buffer,sizeof buffer)!=EOF)
{
printf("T %s",buffer);
char *token = strtok(buffer," ");
while(token!=NULL)
{
printf("T %s\n",token);
write(pipe23[1],token,sizeof token);
token = strtok(NULL, " ");
}
sleep(2);
}
exit(0);
}
Your primary problem is that
read()returns 0 on EOF, not -1 or EOF.Your code should have loops like:
I suggest avoiding the functions registered with
atexit(); they force you to use global variables. Have your primary child functions do their own cleanup. This will make it easier to implement the suggestion made in a comment:This code just about works:
Given a data file containing:
One run of the program produced:
Note that data read with
read()has to be explicitly null terminated; data read withfgets()does not. Note also how the basic debugging was put in place; all inputs are echoed, all outputs to the next program are echoed too. This makes it easy (or, at least, easier) to see where there might be problems. In extreme cases, it would be better to write tostderr, or tofflush()after everyprintf(). There are many details that are sub-optimal, such as usingprintf()with just a single string argument. The tasks structure is redundant in this code. The pipe arrays could be local variables in the revised code.