title: Message queues : Bug with receiving
body: <p>I'm programming a piece of software that uses message queues.
  I have a problem with it: </p>
  
  <p>The main process creates 16 sons (with fork) and each son write a message for the next son. Then, they're waiting to receive their message. (The son "0" sends a message to the son "1", ..., the son "15" sends a message to the son "0").</p>
  
  <p>It works well most of the time but sometimes, something weird happens... A process is never receiving it's message despite it was send by the corresponding son ! I would say that it occurs once after 10 successes.</p>
  
  <p>I've been able to write a piece of code that has the bug:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;time.h&gt;
  #include &lt;termios.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/ipc.h&gt;
  #include &lt;sys/msg.h&gt;
  
  struct buf
  {
      long mtype;
      int data[32];
  };
  
  int main(int arc, char** argv)
  {
      int son = 0;
      int pid = 0;
      struct buf msgbuf;
  
      key_t key;
      key = ftok(argv[0], 'O');
  
      int qid = msgget(key, IPC_CREAT | 0666);
      if(qid &lt; 0)
      {
          printf("Error\n");
          return -1;
      }
  
      //Creates 16 sons
      for(int i = 0; i &lt; 16; i++)
      {
          pid = i;
          son = fork();
          if(son == 0)
              break;
      }
  
      if(son == 0)
      {
          msgbuf.mtype = ((pid + 1) % 16) + 1;
          for(int i = 0; i &lt; 32; i++)
              msgbuf.data[i] = pid;
          printf("Writing %d\n", ((pid + 1) % 16) + 1);
          msgsnd(qid, &amp;msgbuf, 32 * sizeof(int), IPC_NOWAIT);
          printf("Waiting for %d\n", pid + 1);
          msgrcv(qid, &amp;msgbuf, 32 * sizeof(int), pid + 1, 0);
          printf("Got %d\n", (int)msgbuf.mtype);
      }
  
      sleep(3);
      printf("----- END -----\n");
  
      msgctl(qid, IPC_RMID, NULL);
  
      return 0;
  }
  </code></pre>
  
  <p>So, the expected behavior is something like that:</p>
  
  <pre><code>Writing 2
  Writing 3
  Waiting for 1
  Waiting for 2
  Got 2
  Writing 4
  Waiting for 3
  Got 3
  Writing 5
  Waiting for 4
  Got 4
  Writing 6
  Waiting for 5
  Got 5
  Writing 7
  Waiting for 6
  Got 6
  Writing 8
  Waiting for 7
  Got 7
  Writing 9
  Waiting for 8
  Got 8
  Writing 10
  Waiting for 9
  Got 9
  Writing 11
  Waiting for 10
  Got 10
  Writing 12
  Waiting for 11
  Got 11
  Writing 13
  Waiting for 12
  Got 12
  Writing 14
  Waiting for 13
  Got 13
  Writing 15
  Waiting for 14
  Got 14
  Writing 16
  Waiting for 15
  Got 15
  Writing 1
  Waiting for 16
  Got 16
  Got 1
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  </code></pre>
  
  <p>But sometimes, i've got something like that:</p>
  
  <pre><code>Writing 2
  Writing 3
  Waiting for 1
  Waiting for 2
  Got 2
  Writing 4
  Waiting for 3
  Got 3
  Writing 5
  Waiting for 4
  Got 4
  Writing 6
  Waiting for 5
  Got 5
  Writing 7
  Waiting for 6
  Got 6
  Writing 9
  Waiting for 8
  Writing 8
  Waiting for 7
  Got 7
  Got 8
  Writing 10
  Waiting for 9
  Got 9
  Writing 11
  Waiting for 10
  Got 10
  Writing 12
  Waiting for 11
  Got 11
  Writing 13
  Writing 14
  Waiting for 12
  Waiting for 13
  Got 12
  Writing 15
  Waiting for 14
  Got 14
  Writing 16
  Waiting for 15
  Got 15
  Writing 1
  Waiting for 16
  Got 16
  Got 1
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  Got 14
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  ----- END -----
  </code></pre>
  
  <p>As you can see, the message "14" is never received and after 3 seconds, the code frees the queue causes a fake "Got 14".</p>
  
  <p>In my real code, I use semaphores to be sure that the program only exits after everybody receives his message. It implies that a deadlock occurs. Indeed, the message is never received, the semaphore is never "unlocked". So this is NOT because of the sleep time is too short or something like that. This is NOT because I delete the queue afterwards either.</p>
  
  <p>But don't forget that most of the time, this is OK! I don't understand why sometime a son never gets his message.</p>
  
  <p>Can you help me?</p>