The output of my program is not consistent when I redirect standard output to a text file. That is ./main
and ./main > out.txt
have different outputs.
The problem can best be understood by executing the program. Here is my verbal description (in case you would like to read it).
The behavior I get executing with ./main
is what I desire. When redirecting the output, the counter I use in my program appears to be reset which is not intended. I have added some extra print statements to help make it more clear.
What I aimed to do: Generate five child processes, and each process write to a buffer (supported by a pipe). Then in main print the buffer of each child process.
This is what happens without redirecting the output. When I redirect the output, I get a recursive/cascaded result. The result for the first process is correct, but each successive process prints the processes that returned before it.
I used valgrind and did not find any memory leaks. I did notice that more than three FD were open which I think might suggest a file descriptor leak.
- Output 1: goo.gl/Yz534A — without redirection
- Output 2: goo.gl/zfAWQV — with redirection
SO does not allow the use of URL shorteners
Without redirection
Generated separately; equivalent to, but distinct from, the Google doc image.
Fork Instance: 0
Child Process (30869) Terminating...
Exit Status: Normal Value: 0
0 3 buf: Message left from: 30869
The value of i is: 0
Fork Instance: 1
Child Process (30870) Terminating...
Exit Status: Normal Value: 0
1 5 buf: Message left from: 30870
The value of i is: 1
Fork Instance: 2
Child Process (30871) Terminating...
Exit Status: Normal Value: 0
2 7 buf: Message left from: 30871
The value of i is: 2
Fork Instance: 3
Child Process (30872) Terminating...
Exit Status: Normal Value: 0
3 9 buf: Message left from: 30872
The value of i is: 3
Fork Instance: 4
Child Process (30873) Terminating...
Exit Status: Normal Value: 0
4 11 buf: Message left from: 30873
The value of i is: 4
Parent Process (30868) Terminating...
With redirection
Generated separately; equivalent to, but distinct from, the Google doc image.
Fork Instance: 0
Child Process (30791) Terminating...
Fork Instance: 0
Exit Status: Normal Value: 0
0 3 buf: Message left from: 30791
The value of i is: 0
Fork Instance: 1
Child Process (30792) Terminating...
Fork Instance: 0
Exit Status: Normal Value: 0
0 3 buf: Message left from: 30791
The value of i is: 0
Fork Instance: 1
Exit Status: Normal Value: 0
1 5 buf: Message left from: 30792
The value of i is: 1
Fork Instance: 2
Child Process (30793) Terminating...
Fork Instance: 0
Exit Status: Normal Value: 0
0 3 buf: Message left from: 30791
The value of i is: 0
Fork Instance: 1
Exit Status: Normal Value: 0
1 5 buf: Message left from: 30792
The value of i is: 1
Fork Instance: 2
Exit Status: Normal Value: 0
2 7 buf: Message left from: 30793
The value of i is: 2
Fork Instance: 3
Child Process (30794) Terminating...
Fork Instance: 0
Exit Status: Normal Value: 0
0 3 buf: Message left from: 30791
The value of i is: 0
Fork Instance: 1
Exit Status: Normal Value: 0
1 5 buf: Message left from: 30792
The value of i is: 1
Fork Instance: 2
Exit Status: Normal Value: 0
2 7 buf: Message left from: 30793
The value of i is: 2
Fork Instance: 3
Exit Status: Normal Value: 0
3 9 buf: Message left from: 30794
The value of i is: 3
Fork Instance: 4
Child Process (30795) Terminating...
Fork Instance: 0
Exit Status: Normal Value: 0
0 3 buf: Message left from: 30791
The value of i is: 0
Fork Instance: 1
Exit Status: Normal Value: 0
1 5 buf: Message left from: 30792
The value of i is: 1
Fork Instance: 2
Exit Status: Normal Value: 0
2 7 buf: Message left from: 30793
The value of i is: 2
Fork Instance: 3
Exit Status: Normal Value: 0
3 9 buf: Message left from: 30794
The value of i is: 3
Fork Instance: 4
Exit Status: Normal Value: 0
4 11 buf: Message left from: 30795
The value of i is: 4
Parent Process (30789) Terminating...
Code
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#define MAX_NUM 5
int main ()
{
char buf [100];
memset(buf, 0, sizeof buf);
int ret;
pid_t pid;
int mypipefd [MAX_NUM][2];
for (int i = 0; i < MAX_NUM; i++)
{
ret = pipe(mypipefd[i]);
if (ret == -1)
{
perror("\nPipe Error... Exiting\n");
exit(1);
}
}
for (int i = 0; i < MAX_NUM; i++)
{
printf ("\nFork Instance:\t%d\n", i); //Removing trailing \n changes output
pid = fork();
if ( pid == -1)
{
perror("\nFork Error... Exiting\n");
exit(1);
}
else if (pid == 0)
{
int dupRes = dup2(0, mypipefd[i][0]);
if (dupRes == -1)
{
perror("\nDup2 Error... Exiting\n");
exit(1);
}
close(mypipefd[i][0]); // Redundant?
pid_t childID = getpid();
char testString [50];
sprintf(testString, "%s%ld", "Message left from: ", (long) childID );
ssize_t writeResult = write(mypipefd[i][1], testString, strlen(testString));
if (writeResult == -1)
{
perror("\nWriting Error... Exiting\n");
exit(1);
}
printf("\nChild Process (%ld) Terminating...\n", (long) childID);
return 0;
}
else
{
//Credit to: Paul Griffiths [http://stackoverflow.com/questions/35471521/waitstatus-wexitstatusstatus-always-returns-0]
int status;
if ( waitpid( pid, &status, 0 ) != -1 )
{
if (WIFEXITED(status))
{
int retval = WEXITSTATUS(status);
printf("\nExit Status: Normal\tValue: %d",retval);
}
else if (WIFSIGNALED(status))
{
int retSig = WTERMSIG(status);
printf("\nExit Status:\tSignal Exit\tValue:\t%d",retSig);
}
else if (WIFSTOPPED(status))
{
int retSig = WSTOPSIG(status);
printf("\nExit Status:\tStop\tValue:\t%d",retSig);
}
else
{
perror("\nExit Status:WAIT PID UNKNOWN INSTANCE... Terminating\n");
exit(1);
}
}
close(mypipefd[i][1]);
ssize_t readResult = read(mypipefd[i][0], buf, 100);
if (readResult == -1)
{
perror("\nRead Error... Exiting\n");
exit(1);
}
printf("\n%d %d buf:\t%s\n", i, mypipefd[i][0], buf);
memset(buf, 0, sizeof buf);
printf("\nThe value of i is:\t%d\n",i);
}
}
pid_t parentID = getpid();
printf("\nParent Process (%ld) Terminating...\n", (long) parentID);
return 0;
}