2

The following C program is supposed to illustrate race condition b/w child and parent processes :

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

int main()
{
     fork();
     printf("\n 1234567890 \n");
     return 0;
}

When my friends executes it (on Ubuntu), they get expected output, which is jumbled 1234567890s

One example : 12312345645678907890

But when I try the same program on my Arch Linux, it never gives such an output. Its always one after the other.

 1234567890 

 1234567890 

I like that arch linux is some how avoiding race condition, But I would like to disable any such features and would like to get output as my friend's.

6
  • I get the output you describe on arch on my ubuntu 16.04 system. imgur.com/a/2lOlw Commented Apr 22, 2017 at 19:57
  • Could it be related to the compiler used? What were you using? I compiled with gcc version 5.4.0 20160609. Commented Apr 22, 2017 at 20:07
  • @PhilipKirkbride I compiled it with gcc (GCC) 6.3.1 20170306 Commented Apr 22, 2017 at 20:09
  • Could you please try this one and tell me the O/P ? paste.ubuntu.com/24435893 . ( supposed to get jumbled op ) . run it many times. Commented Apr 22, 2017 at 20:13
  • here is what I get with that imgur.com/a/57ic5 Commented Apr 22, 2017 at 20:15

2 Answers 2

3

The printf call would run one or more write(2) system calls, and the order they are processed would be the actual order of the output. One or more, because it depends on the buffering inside the C library. With line-buffered output (going to the terminal), you'd likely get two write calls, once for the initial newline, and another for the rest.

write(1, "\n", 1);
write(1, " 1234567890 \n", 13);

It's possible for another process to be scheduled between the calls, giving first the two empty lines, then the lines with the digits, but given that there's not much processing going on, it's unlikely on an unloaded system.

Note that since both processes print the exact same thing, it doesn't matter which one goes first, as long as one does not interrupt the other.

If the output goes to a file or a pipe, the default is for it to be fully buffered, so you'd probably only get one write call (per process), and no chance of mixed output.

Your example of intermixed digits would be possible if the digits were being output one-by-one, with individual system calls. It's hard to understand why a sensible library implementation would do that when printing a static string whose length is known. With more writes in a loop, intermixed output would be more likely:

Something like this:

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
     int i;
     setbuf(stdout, NULL);  /* explicitly unbuffered */
     int x = fork(); 
     for (i = 0 ; i < 500 ; i++) {
          printf("%d", !!x);
     }
     if (x) {
          wait(NULL);  
          printf("\n");  
     }  
     return 0;  
}

Gives me output like below. Most of the time that is, not always. It's up to the system to decide how to schedule the processes. The unpredictability is why we usually try to avoid race-conditions.

111111111111111111111111111111111111111111111111111111111111111111111111111
111111111111111111111111111111111111111111111111111111111111111111111111111
111100000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000010000001001100
110000000011001100110011000000010011001100110000000100110011001100000001001
100110011000000010011001100110000000100110011001100000001001100110011000000
...
0

My suspicion is that the fork() system call is holding up either the parent or the child process long enough to allow the other process to finish the call to printf() and have the string appear in the output before even getting to its own printf().

Outputting a large number of strings in a loop will probably show the intermingled output that you describe, if both parent and child processes have time to execute the loops concurrently.

"Fixing" this would likely involve rewriting the fork() system call, or components in the kernel involved in it.

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.