1

I am writing a program in which the parent process uses fork() to create N child processes (N is provided as an argument), so that every child is directly forked by this one parent.

Every child process needs to read a line from stdin, and print on to the screen. After compiling and executing the program, the text is provided through a text file like this:

./prog1 3 < fileWithText.txt

My problem is, that I am expecting to see every child "fight" for reading the input, however what I actually see is that there is always only one child process taking care of handling the input. This is the code I use for the child process:

void do_child_reader(int j) {
  int pid;
  int counter = 0;
  char* buffer;
  char* readCheck;
  int readerRunning = TRUE;

  pid = getpid();
  buffer = (char*)malloc(BUFFER_SIZE * sizeof(char));

  while (readerRunning == TRUE) {
    readCheck = fgets(buffer, BUFFER_SIZE, stdin);
    if (readCheck == NULL) {
      readerRunning = FALSE;
    }
    else {
      fprintf(stdout, "(READER %d pid-%d) %s", j, pid, buffer);
      counter++;
    }
  }

  fprintf(stderr, "(READER %d pid-%d) processed %d messages, going to exit\n", j, pid, counter);
  free(buffer);
  exit(counter);
}

Here's the output I get when running for N=3:

(READER 0 pid-72655) I am a message - line 1
(READER 0 pid-72655) I am a message - line 2
(READER 0 pid-72655) I am a message - line 3
(READER 0 pid-72655) processed 3 messages, going to exit
(READER 1 pid-72657) processed 0 messages, going to exit
(READER 2 pid-72659) processed 0 messages, going to exit

The parent process is waiting for the children to finish before exiting.

I am trying to figure out what would cause this behaviour, and whether it is in the way fgets() works or perhaps in the way I am trying to read the strings.

Thank you!

Dilip Kumar
  • 1,736
  • 11
  • 22
Boris Ablamunits
  • 115
  • 1
  • 12
  • Unrelated to your problem, but is there a reason you dynamically allocate the `buffer`? Can't you use an array? Also, be careful with using a variable for `exit`, the C specification only specifies `EXIT_SUCCESS` (which it zero) and `EXIT_FAILURE` (which is `1`). POSIX allows an 8-bit unsigned value (i.e. `0` to `255`) (it actually does a bitwise and with `0xff`). – Some programmer dude Dec 02 '15 at 07:08
  • Thanks, I believe you are right - I could use an array. I think it is a result of previous attempts in understanding the problem. – Boris Ablamunits Dec 02 '15 at 07:29
  • I guess your child processes don't fight for the input because of buffering: all input goes in one chunk to the first one. Why do you need them to fight? :) – user3159253 Dec 02 '15 at 07:40

1 Answers1

3

If the file is so small that one unit of BUFSIZ (from <stdio.h>) bytes can be read by one process, the other processes have nothing left to read. Make the input file bigger — multiple times the size of BUFSIZ — and make sure the clients read slowly enough after getting a buffer full, and you will see them all working on it.

This is I/O buffering for you. You could try messing with setvbuf() to set line buffering on the input; I'm not sure it would work.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thank you! This answers my question and puts the pieces of the puzzle together. Surely, after making the input file bigger and letting the process sleep after input, I saw all the readers in all processes working. I was sure that lines are read one at a time before the code continues to execute and was unaware of the buffer. Thanks again! – Boris Ablamunits Dec 02 '15 at 17:13