title: socket programming: 'accept: Bad file descriptor'
body: <p>I'm trying to write a game that will let multiple clients connect and play - below is the relevant code (it's very messy - cleaning up later):</p>
  
  <p><em>Edit:</em> I realized it's a lot of scrolling... the crash occurs towards the end of the game during:</p>
  
  <pre><code>    std::cout &lt;&lt; black_hits &lt;&lt; " black hits &amp; " &lt;&lt; white_hits
                  &lt;&lt; " white hits.\n";
  
      if (black_hits == 4) {
          std::cout &lt;&lt; "you won!\n";
          std::cin.ignore().get();
          close(client); //&lt;&lt;&lt;&lt; CRASH HERE
          return 0;
      }
  </code></pre>
  
  <p>Not really a crash I guess... but close enough :)</p>
  
  <hr>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;vector&gt;
  #include &lt;algorithm&gt;
  #include &lt;cstdlib&gt;
  #include &lt;ctime&gt;
  #include &lt;string&gt;
  #include &lt;sstream&gt;
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;string.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;netdb.h&gt;
  #include &lt;arpa/inet.h&gt;
  #include &lt;sys/wait.h&gt;
  #include &lt;signal.h&gt;
  
  #define BACKLOG 10
  #define MAXDATASIZE 100
  
  typedef enum {RED,GREEN,BLUE,YELLOW,ORANGE} color;
  int StartMasterMind(int client, sockaddr_storage addr_in); 
  
  struct msgstruct {
          int length;
          char* send_data;
  };
  
  void sigchld_handler(int s)
  {
      while(waitpid(-1, NULL, WNOHANG) &gt; 0);
  }
  
  // get sockaddr, IPv4 or IPv6:
  void *get_in_addr(struct sockaddr *sa)
  {
      if (sa-&gt;sa_family == AF_INET) {
          return &amp;(((struct sockaddr_in*)sa)-&gt;sin_addr);
      }
  
      return &amp;(((struct sockaddr_in6*)sa)-&gt;sin6_addr);
  }
  
  int tcp_connect(const char *serv, const char *host = NULL)
  {
      int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
      struct addrinfo hints, *servinfo, *p;
      struct sockaddr_storage their_addr; // connector's address information
      socklen_t sin_size;
      struct sigaction sa;
      int yes=1;
      char s[INET6_ADDRSTRLEN];
      int rv;
  
      memset(&amp;hints, 0, sizeof hints);
      hints.ai_family = AF_UNSPEC;
      hints.ai_socktype = SOCK_STREAM;
      hints.ai_flags = AI_PASSIVE; // use my IP
  
      if ((rv = getaddrinfo(host, serv, &amp;hints, &amp;servinfo)) != 0) {
          fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
          return 1;
      }
  
      // loop through all the results and bind to the first we can
      for(p = servinfo; p != NULL; p = p-&gt;ai_next) {
          if ((sockfd = socket(p-&gt;ai_family, p-&gt;ai_socktype,
                  p-&gt;ai_protocol)) == -1) {
              perror("server: socket");
              continue;
          }
  
          if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &amp;yes,
                  sizeof(int)) == -1) {
              perror("setsockopt");
              exit(1);
          }
  
          if (bind(sockfd, p-&gt;ai_addr, p-&gt;ai_addrlen) == -1) {
              close(sockfd);
              perror("server: bind");
              continue;
          }
  
          break;
      }
  
      if (p == NULL)  {
          fprintf(stderr, "server: failed to bind\n");
          return 2;
      }
  
      freeaddrinfo(servinfo); // all done with this structure
  
      if (listen(sockfd, BACKLOG) == -1) {
          perror("listen");
          exit(1);
      }
  
      sa.sa_handler = sigchld_handler; // reap all dead processes
      sigemptyset(&amp;sa.sa_mask);
      sa.sa_flags = SA_RESTART;
      if (sigaction(SIGCHLD, &amp;sa, NULL) == -1) {
          perror("sigaction");
          exit(1);
      }
  
      printf("server: waiting for connections...\n");
  
      while(1) {  // main accept() loop
          sin_size = sizeof their_addr;
          new_fd = accept(sockfd, (struct sockaddr *)&amp;their_addr, &amp;sin_size);
          if (new_fd == -1) {
              perror("accept");
              continue;
          }
  
          inet_ntop(their_addr.ss_family,
              get_in_addr((struct sockaddr *)&amp;their_addr),
              s, sizeof s);
          printf("server: got connection from %s\n", s);
  
          if (!fork()) { // this is the child process
              close(sockfd); // child doesn't need the listener
              //if (send(new_fd, "Hello, world!", 13, 0) == -1)
              //    perror("send");
              //close(new_fd);
              StartMasterMind(new_fd,their_addr);
             // exit(0);
          }
          close(new_fd);  // parent doesn't need this
      }
  
      return 0;
  }
  
  void InitializeGame(const char* port)
  {
      tcp_connect(port);
  }
  
  std::vector&lt;color&gt; GetInputAsColorMap(char* input)
  {
  [...]//redacted for clarity
  }
  
  int StartMasterMind(int client, sockaddr_storage addr_in) 
  {
      struct msgstruct message;   
      struct sockaddr_storage their_addr = addr_in;
      socklen_t addr_len;
  
      message.send_data = "Welcome to ... M A S T E R M I N D.\n";
      message.length = strlen(message.send_data);
      send(client, message.send_data, message.length, 0);
  
  [...]//redacted for clarity
  
      if (strcmp(theValue, "random") == 0 || strcmp(theValue, "Random") == 0)
      {
  [...]//redacted for clarity
      }
      else
      {
  [...]//redacted for clarity
      }
  
  
      char* buf;
  
      for (int i = 0; i &lt; 8; ++i) {
          std::vector&lt;color&gt; current_try(4);
          int black_hits = 0, white_hits = 0;
          std::vector&lt;int&gt; correctColorIndex;
          std::vector&lt;int&gt; correctColor;
  
          bool exclude[4] = {false};
          std::cout &lt;&lt; "test\n"; 
          message.send_data = "Please enter your guess:  ";
          message.length = strlen(message.send_data);
          send(client, message.send_data, message.length, 0);
  
          addr_len = sizeof their_addr;
          std::cout &lt;&lt; "addr_len: " &lt;&lt; addr_len &lt;&lt; std::endl;     
  
          recvfrom(client, buf, MAXDATASIZE-1, 0, (struct sockaddr *)&amp;their_addr, &amp;addr_len);
  
          current_try = GetInputAsColorMap(buf);
          std::cout &lt;&lt; "the buffer: " &lt;&lt; buf &lt;&lt; std::endl;
          std::cout &lt;&lt; "current_try: " &lt;&lt; current_try[0] &lt;&lt; current_try[1] &lt;&lt; current_try[2] &lt;&lt; current_try[3] &lt;&lt; std::endl;
  
  [...]//redacted for clarity
  
          std::cout &lt;&lt; black_hits &lt;&lt; " black hits &amp; " &lt;&lt; white_hits
                      &lt;&lt; " white hits.\n";
  
          if (black_hits == 4) {
              std::cout &lt;&lt; "you won!\n";
              std::cin.ignore().get();
              close(client); //&lt;&lt;&lt;&lt; CRASH HERE
              return 0;
          }
      }   
  
  [...]//redacted for clarity
  }
  
  int main(int argc, char** argv)
  {
      InitializeGame(argv[1]);
      return 0;
  }
  </code></pre>
  
  <hr>
  
  <p><strong>Here is sample output:</strong></p>
  
  <pre><code>server: waiting for connections...
  server: got connection from 127.0.0.1
  value or random: 
  1122
  test
  addr_len: 128
  the buffer: 1123�
  current_try: 1123
  3 black hits &amp; 0 white hits.
  test
  addr_len: 128
  the buffer: 1223�
  current_try: 1223
  2 black hits &amp; 1 white hits.
  test
  addr_len: 128
  the buffer: 1122�
  current_try: 1122
  4 black hits &amp; 0 white hits.
  you won!
  accept: Bad file descriptor
  accept: Bad file descriptor
  accept: Bad file descriptor
  ... // continuously, hundreds of times
  </code></pre>
  
  <hr>
  
  <p>I'm very new to socket programming; could someone give me a hand? This crashes with or without trying to <code>close(client)</code> at the end of the game.</p>