title: Multithreaded TCP server with C sockets and pthreads - Why does accept() block on the second request?
body: <p>I've been writing a small multithreaded TCP server in C using unix sockets and pthreads, but I'm having trouble with accept(). It hangs on the second request that comes through, and only unblocks when the previously thread exits.</p>
  
  <p>Here's how I set up the server socket.</p>
  
  <pre><code>int server_start(server_t *server, int port) {
      int fd;
      struct sockaddr_in server_addr;
  
      // Socket file descriptor.
      fd = socket(AF_INET, SOCK_STREAM, 0);
      if (fd == -1) {
          perror("socket failed");
          return 1;
      }
  
      // Socket address.
      server_addr.sin_family      = AF_INET;
      server_addr.sin_addr.s_addr = INADDR_ANY;
      server_addr.sin_port        = htons(port);
  
      // Bind.
      if (bind(fd, (struct sockaddr *) &amp;server_addr, sizeof(server_addr)) == -1) {
          perror("bind failed");
          return 1;
      }
  
      server-&gt;fd = fd;
      listen(server-&gt;fd, server-&gt;clients_len);
      pthread_create(&amp;(server-&gt;thread), NULL, thread_entry_server, server);
  
      return 0;
  }
  </code></pre>
  
  <p>Here's my add_client code. It spawns a separate thread for the client.</p>
  
  <pre><code>client_t *server_add_client(server_t *server) {
  
      int iter,
          fd,
          status;
      client_t *client;
  
      printf("before\n");
      fd = accept(server-&gt;fd, NULL, 0);
      printf("after\n");
  
      if (fd == -1) {
          perror("accept");
          return NULL; // Connection failed.
      }
  
      // Find an empty spot.
      client = server-&gt;get_empty_spot();
      client-&gt;fd = fd;
  
      // Start the new thread.
      status = pthread_create(
          &amp;(client-&gt;thread),
          NULL,
          thread_entry_client,
          client
      );
      if (status != 0) {
          perror("pthread_create");
          close(client-&gt;fd);
          return NULL;
      }
  
      client-&gt;active = 1;
  
      return client;
  }
  </code></pre>
  
  <p>And here's my entry function for the client thread:</p>
  
  <pre><code>void *thread_entry_client(void *void_client) {
  
      client_t *client = void_client;
      int len;
  
      while (1) {
  
          len = recv(client-&gt;fd, client-&gt;recv_buffer, RECV_BUFFER_LEN, 0);
          if (len &lt; 0) {
              perror("recv");
              client-&gt;active = 0;
              close(client-&gt;fd);
              return NULL;
          }
          if (len == 0) { // Client disconnected.
              client-&gt;active = 0;
              close(client-&gt;fd);
              printf("disconnect\n");
              return NULL;
          }
  
          if (len &gt; 0) {
              //printf("%s\n", client-&gt;recv_buffer);
              printf("msg\n");
          }
      }
  
      return NULL;
  }
  </code></pre>
  
  <p>So what I'm doing to test this is establishing two connections. The first connection goes through and works fine, but the second connection does not - instead the thread hangs on accept(). I know this from my printfs (that I've left in there), and I know that accept() unblocks AFTER the first client disconnects. I also know that my code is not closing the server socket file descriptor or changing it.</p>
  
  <p>Any advice on debugging this? I can't figure it out.</p>
  
  <p>EDIT: Here is thread_entry_server.</p>
  
  <pre><code>void *thread_entry_server(void *void_server) {
      server_t *server = void_server;
      client_t *client;
  
      while (1) {
          client = server_add_client(server);
          if (client == NULL) // Server is full or connection failed.
              continue;
      }
  
      return NULL;
  }
  </code></pre>