title: Multhreaded programming in C
body: <p>I have been given an assignment. There is a dictionary of 25 files and each file has random text involving random IP addresses. The task is to find out and output the count of unique IP addresses among all files using the <code>pthread</code> library in C.</p>
  
  <p>I think I have solved the race condition on count variable by mutual exclusion. But, still there is a bug and the code has different count value in each execution.</p>
  
  <p>Here is the code, please suggest fixes for the bug:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;dirent.h&gt;
  #include &lt;pthread.h&gt;
  #include &lt;string.h&gt;
  
  //declaring structure of arguments to give arguments to thread function
  struct arg_struct
  {
     char *arg1; //argument 1 : to pass directory name to thread function
     struct dirent *arg2;    //argument 2: to pass file name to thread function
  };
  
  //declaring structure of pointer which will point unique ip addresses
  struct uniqueip
  {
      char *ip;
  };
  
  struct filenames
  {
      char full_filename[256];
  };
  
  struct uniqueip u[200];
  
  int count=0;// global count variable stores total unique ip addresses.
  void *ReadFile(void *thread_no);//thread declaration
  pthread_mutex_t mutex;
  
  int main(int argc, char *argv[])
  {
      DIR *dir;   //directory stream
      FILE *file; //file stream
      struct dirent *ent; // directory entry structure
      char *line = NULL;  // pointer to
      size_t len = 1000;  //the length of bytes getline will allocate
      size_t read;
  
      char full_filename[256];    //will hold the entire file path with
                                   //file name to read
  
      int x=0;
  
      pthread_attr_t attr;
        int rc;
            long thread_no;
        void *status;
        void *ReadFile(void *thread_no);
  
        // check the arguments
      if(argc &lt; 2)
      {
          printf("Not enough arguments supplied\n");
          return -1;
      }
  
      if(argc &gt; 2)
      {
          printf("Too many arguments supplied\n");
          return -1;
      }
  
         struct arg_struct args;
         args.arg1 = argv[1];
  
         pthread_mutex_init(&amp;mutex, NULL); // initializing mutex
  
         /* Initialize and set thread detached attribute */
         pthread_attr_init(&amp;attr);
         pthread_attr_setdetachstate(&amp;attr, PTHREAD_CREATE_JOINABLE);
          // try to open the directory given by the argument
          if ((dir = opendir (argv[1])) != NULL)
          {
              /* print all the files and directories within directory */
              while ((ent = readdir (dir)) != NULL)
              {
  
                  // Check if the list is a regular file
                  if(ent-&gt;d_type == DT_REG)
                  {
                      //Get the number of files first so that we would know number
                      //of threads to be created
                      x++;
                  }
              }
          }
  
          pthread_t thread[x];
          struct filenames filenames[x];
          thread_no=0;
  
          // try to open the directory given by the argument
              if ((dir = opendir (argv[1])) != NULL)
              {
          /* print all the files and directories within directory */
          while ((ent = readdir (dir)) != NULL)
          {
  
              // Check if the list is a regular file
              if(ent-&gt;d_type == DT_REG)
              {
                  // Create the absolute path of the filename
                  snprintf(filenames[thread_no].full_filename, sizeof filenames[thread_no].full_filename, 
                  "./%s/%s", argv[1], ent-&gt;d_name);
                  //creating threads to read files
                  args.arg2 = ent; //assigning file name to argument 2
  
                  printf("main: creating thread %ld  %s \n", thread_no,ent-&gt;d_name);
  
                  rc = pthread_create(&amp;thread[thread_no], &amp;attr, ReadFile, (void *) &amp;args);
                  if (rc)
                  {
                           printf("ERROR; return code from pthread_create() is %d\n", rc);
                           exit(-1);
                  }
                  thread_no++;
              }
          }
              // Close the directory structure
              closedir (dir);
          }
          else
          {
              /* could not open directory */
              perror ("");
              return -1;
          }
  
                     /* Free attribute and wait for the other threads*/
          pthread_attr_destroy(&amp;attr);
          for(thread_no=0; thread_no&lt;x; thread_no++)
          {
               rc = pthread_join(thread[thread_no], &amp;status);
                       if (rc)
               {
                  printf("ERROR; return code from pthread_join() is %d\n", rc);
                  exit(-1);
               }
               printf("Main: completed join with thread %ld having a status of %ld\n",thread_no,(long)status);
          }
          printf("Main: program completed. Exiting.\n");
              printf("total no. of unique ip addresses are %d\n",count-1);
              pthread_mutex_destroy(&amp;mutex);
          pthread_exit(NULL);
                  return 0;
  }
  
  
  
  void *ReadFile(void *thread_no)
  {  // in thread function
      struct filenames *my_data;
      my_data = (struct filenames *)thread_no;
  
      char full_filename[256];
      FILE *file;    //file stream
      char *line = NULL;
      char *split = NULL;
      size_t len = 1000;    // pointer to the length of bytes getline will allocate
      size_t read;
      const char s[2]=" "; //used as string split to get ip address
      char *token;
      int flag = 0,j;
  
      // open the file
      file = fopen(my_data -&gt; full_filename, "r");
      // file was not able to be open
  
      if (file != NULL)
      {
      //     Print out each line in the file
  
      while ((read = getline(&amp;line, &amp;len, file)) != -1)
       {
                split=line;
                token = strtok(split,s);
  
            pthread_mutex_lock(&amp;mutex);   
            if(count==0){
                    //locking mutex variable to avoid race condition
                    u[count].ip=malloc(sizeof(token)+1);
                    strcpy(u[count].ip,token);
                    printf("%d ------ %s\n",count,u[count].ip); 
                    free(u[count].ip);
                    count++;
          }
          pthread_mutex_unlock(&amp;mutex); // unlocking mutex
                  //comparing recently received ip address to all the stored unique ip address.
                  for(j=0;j&lt;count;j++)
                  {
                      if(!(strcmp(u[j].ip,token)))
                      {
                           break;
                      }
                      else
                      {     
                   if(j==count-1){                
                    pthread_mutex_lock(&amp;mutex); //locking mutex variable to avoid race condition
                    u[count].ip=malloc(sizeof(read));
                    strcpy(u[count].ip,token);
                    printf("%d ------ %s\n",count,u[count].ip);
                    count++;
                    free(u[count].ip);
                    pthread_mutex_unlock(&amp;mutex); // unlocking mutex
                    }
              }
                  }
          }
  
  
       }
  
      fclose(file);
      pthread_exit((void*) thread_no);
  
  }
  </code></pre>