title: Socket descriptor not getting released on doing 'close ()' for a multi-threaded UDP client
body: <p>I have written below UDP client which basically spawns a separate thread for receiving the data-grams however the data-grams are being sent in the main thread only. Now, having pressed ctrl^D post instantiating ("./udpClient   1") the UDP client on Linux distribution, the implementation comes out of the loop (around the getline () call) and closes the socket descriptor. </p>
  
  <p>What I had observed that despite calling close on the descriptor the same is not released until the client process is terminated and still seeing the associated entry on doing "netstat -an|grep udp". However, if I comment/delete out the code to spawn the receiver thread then the socket descriptor is released immediately having called close ().</p>
  
  <p>It seems socket reference count is getting incremented on spawning a separate thread (which basically receives and blocks on the said socket descriptor) and hence the close () call does nothing. </p>
  
  <p>Is this desired since I was of the understanding that socket reference count is increased if the socket descriptor is shared across processes but not across threads? Is it because of the Linux implementation of the threads as LWP and if so, is this the desired behavior?</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;strings.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/socket.h&gt;
  #include &lt;netinet/in.h&gt;
  #include &lt;errno.h&gt;
  
  void *receiver (void *arg);
  
  int sockfd;
  
  int doConnect = 0;
  
  int
  main (int argc, char *argv[])
  {
      pthread_t thrid;
  
      struct sockaddr_in servaddr;
  
      struct sockaddr_in clntaddr;
  
      char *line;
  
      size_t len = 0;
  
      size_t read;
  
      if (argc &lt; 4)
      {
          printf
              ("Usage:%s &lt;Server Ipv4 address&gt; &lt;Server Port&gt; &lt;Connect Yes(1)/No(0)&gt; [Client IPv4 address] [Client Port]\n",
               argv[0]);
          return -1;
      }
  
  
      /*
       * AF_INET, AF_INET6, AF_UNIX, AF_NETLINK
       * SOCK_STREAM (TCP), SOCK_DGRAM (UDP), SOCK_RAW
       */
      if ((sockfd = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
      {
          printf ("Failed to create socket: %s\n", strerror (errno));
          return -1;
      }
  
      bzero (&amp;clntaddr, sizeof (struct sockaddr_in));
  
      if (argc == 6)
      {
          printf ("doing bind......\n");
          clntaddr.sin_family = AF_INET;
          clntaddr.sin_port = htons (atoi (argv[5]));
          inet_aton (argv[4], &amp;clntaddr.sin_addr);
  
          if (bind
              (sockfd, (struct sockaddr *) &amp;clntaddr,
               sizeof (struct sockaddr_in)) == -1)
          {
              printf ("Failed to bind: %s\n", strerror (errno));
              close (sockfd);
              return -1;
          }
      }
  
      /*
       * fill up the server details
       */
      bzero (&amp;servaddr, sizeof (struct sockaddr_in));
  
      servaddr.sin_family = AF_INET;
      servaddr.sin_port = htons (atoi (argv[2]));
      inet_aton (argv[1], &amp;servaddr.sin_addr);
  
      doConnect = atoi (argv[3]);
  
      if (1 == doConnect)
      {
          printf ("doing connect......\n");
          if (-1 ==
              connect (sockfd, (struct sockaddr *) &amp;servaddr,
                       sizeof (struct sockaddr_in)))
          {
              printf ("Failed to connect: %s\n", strerror (errno));
              close (sockfd);
              return -1;
          }
      }
  
      if (pthread_create (&amp;thrid, NULL, receiver, NULL) &lt; 0)
      {
          printf ("Failed to create thread: %s\n", strerror (errno));
          close (sockfd);
          return -1;
      }
  
      while ((read = getline (&amp;line, &amp;len, stdin)) != -1)
      {
          if (1 == doConnect)
          {
              if (send (sockfd, line, len, 0) &lt; 0)
              {
                  printf ("send () failed: %s\n", strerror (errno));
              }
          }
          else
          {
              if (sendto (sockfd, line, len, 0, (struct sockaddr *) &amp;servaddr,
                          sizeof (struct sockaddr_in)) &lt; 0)
              {
                  printf ("sendto () failed: %s\n", strerror (errno));
              }
          }
      }
  
      if (line)
          free (line);
  
      close (sockfd);
  
      printf ("socket is closed.....\n");
  
      sleep (60);
  }
  
  void *
  receiver (void *arg)
  {
      char buff[512];
  
      while (1)
      {
          memset (buff, 0, sizeof (buff));
  
          if (1 == doConnect)
          {
              if (recv (sockfd, buff, sizeof (buff), 0) &lt; 0)
              {
                  // printf ("recvfrom () failed: %s\n", strerror (errno));
                  printf ("recv () failed\n");
              }
              else
              {
                  printf ("recv () returned: %s\n", buff);
              }
          }
          else
          {
              if (recvfrom (sockfd, buff, sizeof (buff), 0, NULL, NULL) &lt; 0)
              {
                  // printf ("recvfrom () failed: %s\n", strerror (errno));
                  printf ("recvfrom () failed\n");
              }
              else
              {
                  printf ("recvfrom () returned: %s\n", buff);
              }
          }
      }
  }
  </code></pre>