title: C uninitialized mutex works and initialized mutex fails?
body: <p>My C program creates a producer thread, saving data as fast as possible. The main thread consumes and prints these.</p>
  
  <p>After days of bug finding, I noticed that if the mutex was initialized, then the program stops within 30 seconds (deadlock?).</p>
  
  <p>However if the mutex is left uninitialized it works perfectly.</p>
  
  <p>Can anyone explain this?? To avoid undefined behavior, I would prefer to initialize them if possible.</p>
  
  <p><strong>Further Info:</strong> Specifically it's locking up if "pthread_mutex_t signalM" (the signaling mutex) is initialized</p>
  
  <p><strong>Initialized</strong></p>
  
  <pre><code>#include &lt;stdlib.h&gt;                     // exit_failure, exit_success
  #include &lt;stdio.h&gt;                      // stdin, stdout, printf
  #include &lt;pthread.h&gt;                    // threads
  #include &lt;string.h&gt;                     // string
  #include &lt;unistd.h&gt;                     // sleep
  #include &lt;stdbool.h&gt;                    // bool
  #include &lt;fcntl.h&gt;                      // open
  
  
  
  struct event {
      pthread_mutex_t critical;
      pthread_mutex_t signalM;
      pthread_cond_t signalC;
      int eventCount;
  };
  
  struct allVars {
      struct event inEvents;
      struct event outEvents;
      int bufferSize;
      char buffer[10][128];
  };
  
  
  
  
  /**
   * Advance the EventCount
   */
  void advance(struct event *event) {
      // increment the event counter
      pthread_mutex_lock(&amp;event-&gt;critical);
      event-&gt;eventCount++;
      pthread_mutex_unlock(&amp;event-&gt;critical);
  
      // signal await to continue
      pthread_mutex_lock(&amp;event-&gt;signalM);
      pthread_cond_signal(&amp;event-&gt;signalC);
      pthread_mutex_unlock(&amp;event-&gt;signalM);
  }
  
  
  
  /**
   * Wait for ticket and buffer availability
   */
  void await(struct event *event, int ticket) {
  
      int eventCount;
  
      // get the counter
      pthread_mutex_lock(&amp;event-&gt;critical);
      eventCount = event-&gt;eventCount;
      pthread_mutex_unlock(&amp;event-&gt;critical);
  
      // lock signaling mutex
      pthread_mutex_lock(&amp;event-&gt;signalM);
  
      // loop until the ticket machine shows your number
      while (ticket &gt; eventCount) {
          // wait until a ticket is called
          pthread_cond_wait(&amp;event-&gt;signalC, &amp;event-&gt;signalM);
  
          // get the counter
          pthread_mutex_lock(&amp;event-&gt;critical);
          eventCount = event-&gt;eventCount;
          pthread_mutex_unlock(&amp;event-&gt;critical);
      }
  
      // unlock signaling mutex
      pthread_mutex_unlock(&amp;event-&gt;signalM);
  }
  
  
  
  /**
   * Add to buffer
   */
  void putBuffer(struct allVars *allVars, char data[]) {
      // get the current write position
      pthread_mutex_lock(&amp;allVars-&gt;inEvents.critical);
      int in = allVars-&gt;inEvents.eventCount;
      pthread_mutex_unlock(&amp;allVars-&gt;inEvents.critical);
  
      // wait until theres a space free in the buffer
      await(&amp;allVars-&gt;outEvents, in - allVars-&gt;bufferSize + 1);   // set to 2 to keep 1 index distance
  
      // add data to buffer
      strcpy(allVars-&gt;buffer[in % allVars-&gt;bufferSize], data);
  
      // increment the eventCounter and signal
      advance(&amp;allVars-&gt;inEvents);
  }
  
  
  
  /**
   * Get from buffer
   */
  char *getBuffer(struct allVars *allVars) {
      // get the current read position
      pthread_mutex_lock(&amp;allVars-&gt;outEvents.critical);
      int out = allVars-&gt;outEvents.eventCount;
      pthread_mutex_unlock(&amp;allVars-&gt;outEvents.critical);
  
      // wait until theres something in the buffer
      await(&amp;allVars-&gt;inEvents, out + 1);
  
      // allocate memory for returned string
      char *str = malloc(128);
  
      // get the buffer data
      strcpy(str, allVars-&gt;buffer[out % allVars-&gt;bufferSize]);
  
      // increment the eventCounter and signal
      advance(&amp;allVars-&gt;outEvents);
  
      return str;
  }
  
  
  
  /** child thread (producer) */
  void *childThread(void *allVars) {
      char str[10];
      int count = 0;
  
      while (true) {
          sprintf(str, "%d", count++);
          putBuffer(allVars, str);
      }
  
      pthread_exit(EXIT_SUCCESS);
  }
  
  
  
  int main(void) {
      // init structs
      struct event inEvents = {
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_COND_INITIALIZER,
          0
      };
      struct event outEvents = {
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_COND_INITIALIZER,
          0
      };
      struct allVars allVars = {
          inEvents,       // events
          outEvents,
          10,             // buffersize
          {"", {""}}      // buffer[][]
      };
  
  
      // create child thread (producer)
      pthread_t thread;
      if (pthread_create(&amp;thread, NULL, childThread, &amp;allVars)) {
          fprintf(stderr, "failed to create child thread");
          exit(EXIT_FAILURE);
      }
  
  
      // (consumer)
      while (true) {
          char *out = getBuffer(&amp;allVars);
          printf("buf: %s\n", out);
          free(out);
      }
  
  
      return (EXIT_SUCCESS);
  }
  </code></pre>
  
  <p><strong>Uninitialized</strong></p>
  
  <pre><code>#include &lt;stdlib.h&gt;                     // exit_failure, exit_success
  #include &lt;stdio.h&gt;                      // stdin, stdout, printf
  #include &lt;pthread.h&gt;                    // threads
  #include &lt;string.h&gt;                     // string
  #include &lt;unistd.h&gt;                     // sleep
  #include &lt;stdbool.h&gt;                    // bool
  #include &lt;fcntl.h&gt;                      // open
  
  
  
  struct event {
      pthread_mutex_t critical;
      pthread_mutex_t signalM;
      pthread_cond_t signalC;
      int eventCount;
  };
  
  struct allVars {
      struct event inEvents;
      struct event outEvents;
      int bufferSize;
      char buffer[10][128];
  };
  
  
  
  
  /**
   * Advance the EventCount
   */
  void advance(struct event *event) {
      // increment the event counter
      pthread_mutex_lock(&amp;event-&gt;critical);
      event-&gt;eventCount++;
      pthread_mutex_unlock(&amp;event-&gt;critical);
  
      // signal await to continue
      pthread_mutex_lock(&amp;event-&gt;signalM);
      pthread_cond_signal(&amp;event-&gt;signalC);
      pthread_mutex_unlock(&amp;event-&gt;signalM);
  }
  
  
  
  /**
   * Wait for ticket and buffer availability
   */
  void await(struct event *event, int ticket) {
  
      int eventCount;
  
      // get the counter
      pthread_mutex_lock(&amp;event-&gt;critical);
      eventCount = event-&gt;eventCount;
      pthread_mutex_unlock(&amp;event-&gt;critical);
  
      // lock signaling mutex
      pthread_mutex_lock(&amp;event-&gt;signalM);
  
      // loop until the ticket machine shows your number
      while (ticket &gt; eventCount) {
          // wait until a ticket is called
          pthread_cond_wait(&amp;event-&gt;signalC, &amp;event-&gt;signalM);
  
          // get the counter
          pthread_mutex_lock(&amp;event-&gt;critical);
          eventCount = event-&gt;eventCount;
          pthread_mutex_unlock(&amp;event-&gt;critical);
      }
  
      // unlock signaling mutex
      pthread_mutex_unlock(&amp;event-&gt;signalM);
  }
  
  
  
  /**
   * Add to buffer
   */
  void putBuffer(struct allVars *allVars, char data[]) {
      // get the current write position
      pthread_mutex_lock(&amp;allVars-&gt;inEvents.critical);
      int in = allVars-&gt;inEvents.eventCount;
      pthread_mutex_unlock(&amp;allVars-&gt;inEvents.critical);
  
      // wait until theres a space free in the buffer
      await(&amp;allVars-&gt;outEvents, in - allVars-&gt;bufferSize + 1);   // set to 2 to keep 1 index distance
  
      // add data to buffer
      strcpy(allVars-&gt;buffer[in % allVars-&gt;bufferSize], data);
  
      // increment the eventCounter and signal
      advance(&amp;allVars-&gt;inEvents);
  }
  
  
  
  /**
   * Get from buffer
   */
  char *getBuffer(struct allVars *allVars) {
      // get the current read position
      pthread_mutex_lock(&amp;allVars-&gt;outEvents.critical);
      int out = allVars-&gt;outEvents.eventCount;
      pthread_mutex_unlock(&amp;allVars-&gt;outEvents.critical);
  
      // wait until theres something in the buffer
      await(&amp;allVars-&gt;inEvents, out + 1);
  
      // allocate memory for returned string
      char *str = malloc(128);
  
      // get the buffer data
      strcpy(str, allVars-&gt;buffer[out % allVars-&gt;bufferSize]);
  
      // increment the eventCounter and signal
      advance(&amp;allVars-&gt;outEvents);
  
      return str;
  }
  
  
  
  /** child thread (producer) */
  void *childThread(void *allVars) {
      char str[10];
      int count = 0;
  
      while (true) {
          sprintf(str, "%d", count++);
          putBuffer(allVars, str);
      }
  
      pthread_exit(EXIT_SUCCESS);
  }
  
  
  
  int main(void) {
      // init structs
      struct event inEvents; /* = {
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_COND_INITIALIZER,
          0
      }; */
      struct event outEvents; /* = {
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_MUTEX_INITIALIZER,
          PTHREAD_COND_INITIALIZER,
          0
      }; */
  
      struct allVars allVars = {
          inEvents,       // events
          outEvents,
          10,             // buffersize
          {"", {""}}      // buffer[][]
      };
  
  
      // create child thread (producer)
      pthread_t thread;
      if (pthread_create(&amp;thread, NULL, childThread, &amp;allVars)) {
          fprintf(stderr, "failed to create child thread");
          exit(EXIT_FAILURE);
      }
  
  
      // (consumer)
      while (true) {
          char *out = getBuffer(&amp;allVars);
          printf("buf: %s\n", out);
          free(out);
      }
  
  
      return (EXIT_SUCCESS);
  }
  </code></pre>