Why does this program using fork() and wait() output 201 when I run it?
-
When I diagrammed this, I wrote that the possible outputs could be 3020140, 1203040, 2013040, 1302040, or 3012040. When I ran it, the output was 201. What's going on? How could the program never reach 3, and what's happening with the wait condition? I thought wait meant that that calling process would not continue until children processes had finished, meaning that it would always be at the end of output. int main() { if (fork() != 0) { if (fork() == 0) { printf("3"); } else { pid_t pid ; int status ; if ((pid = wait(&status)) > 0) { printf("4"); } } } else { if (fork() == 0) { printf("1"); exit (0); } printf("2"); } printf("0"); return 0; }
-
Answer:
One observation: the complete lack of newlines in the print statements means that the output is only flushed when the processes terminate. This makes it harder to see what's going on. Because the characters will be flushed when the process exits, one non-zero digit and its following zero will normally appear together. Superficially, the 30 should appear before the 40. However, the child that dies first could be the one that controls the printing of 1 and 20, in which case, the 40 could appear before the 30 is printed. Note that the wait() function only waits for one child to die before returning, unlike the shell command wait with no arguments which waits for all children to die. There's no guarantee about the relative sequencing of 1 (which won't be followed by a 0) and 20, and no guarantee about the sequencing of 30, 40 compared with 1 and 20. The code can fail to print 3 if the fork before it fails. When I ran the unmodified code a few times (I called the program f7), I got the output: $ ./f7;echo 2040 301$ ./f7;echo 3020140 $ ./f7;echo 203040 1$ ./f7;echo 2030140 $ ./f7;echo 2013040 $ This demonstrates that the sequencing is rather arbitrary. Sometimes, the echo completed before some of the children did. Note that the first run shows 40 appearing before 30 or 1; I didn't even have to be selective about which runs I showed. The machine happens to be a 12 logical core Intel-based machine running an Ubuntu 14.04 derivative, so there are plenty of cores available for child processes to use. The first thing I'd do is add lots of diagnostic printing (with newlines) identifying what is happening where. That means each output would include the PID. The various parent processes would identify the PID of their children; the wait would report on the PID which was reported as dead. The instrumentation is written to standard error with a newline at the end of each printing operation. The output is also echoed to standard output as originally. I saved this code in f11.c and therefore ran it as ./f11: #include "posixver.h" #include <stdio.h> #include <sys/wait.h> #include <unistd.h> static void print(const char *number) { fprintf(stderr, "[%d:%s]\n", (int)getpid(), number); printf("%s", number); } int main(void) { pid_t pid; fprintf(stderr, "[%d:initial]\n", (int)getpid()); if ((pid = fork()) != 0) { fprintf(stderr, "[%d:parent-1;child=%d]\n", (int)getpid(), (int)pid); if ((pid = fork()) == 0) { print("3"); } else { fprintf(stderr, "[%d:parent-2;child=%d]\n", (int)getpid(), (int)pid); int status; if ((pid = wait(&status)) > 0) { fprintf(stderr, "[%d:corpse=%d;status=0x%.4X]\n", (int)getpid(), (int)pid, status); print("4"); } } } else { fprintf(stderr, "[%d:child]\n", (int)getpid()); if ((pid = fork()) == 0) { print("1"); exit(0); } fprintf(stderr, "[%d:parent-3;child=%d]\n", (int)getpid(), (int)pid); print("2"); } print("0"); return 0; } Example run: $ ./f11;echo [6781:initial] [6781:parent-1;child=6782] [6782:child] [6781:parent-2;child=6783] [6782:parent-3;child=6784] [6782:2] [6782:0] [6784:1] 201[6783:3] [6781:corpse=6782;status=0x0000] [6781:4] [6783:0] [6781:0] 4030 $ Without the standard error, the output sequence would have been 2014030. Note that I always saw the complete output (a 20, a 30, a 40, and a 1). If you missed some output, it might be because your PS1 prompt overwrote it (which would require an unusual but not impossible value for PS1 that included a carriage return).
Anderson Cook at Stack Overflow Visit the source
Related Q & A:
- Why do the colors on my pictures look washed out when i upload them?Best solution by Yahoo! Answers
- Why do my bones hurt when I run?Best solution by healthtap.com
- What are the yahoo points for? And what happens when I run out of them?Best solution by Yahoo! Answers
- Why my car feels like it wants to shut off when I start the engine it a Ford Focus 2003?Best solution by Yahoo! Answers
- Why does my laptop freeze when i scroll and why cant i use my taskbar?Best solution by Yahoo! Answers
Just Added Q & A:
- How many active mobile subscribers are there in China?Best solution by Quora
- How to find the right vacation?Best solution by bookit.com
- How To Make Your Own Primer?Best solution by thekrazycouponlady.com
- How do you get the domain & range?Best solution by ChaCha
- How do you open pop up blockers?Best solution by Yahoo! Answers
For every problem there is a solution! Proved by Solucija.
-
Got an issue and looking for advice?
-
Ask Solucija to search every corner of the Web for help.
-
Get workable solutions and helpful tips in a moment.
Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.