1

I want to read a specific line from file and return it from thread function but the function don't return any thing

this is the thread function:

static void* read_line(void* th_arg){
 struct arg* current = (struct arg*)th_arg;
 char buffer[MAX_LINE_SIZE];
 char* return_str;
 bool keep_reading = true;
 int  current_line = 1;

 do{
    fgets(buffer, sizeof(buffer), current->file_name);
    if(feof(current->file_name)){
      keep_reading = false;
    }
    else if(current_line++ == current->line){
      keep_reading = false;
      return_str = buffer;
      pthread_exit((void*)return_str); // return the string
    }
  } while(keep_reading);
  
  printf("\n no return from the thread function\n");
  pthread_exit(NULL); // return NULL
}

the function that create the thread:

bool check_account(struct info* temp, char* email, char* password){

  char fileName[FILE_NAME_SIZE];

  strcpy(fileName,temp->folder_name);
  strcat(fileName,"/");
  strcat(fileName,email);
  strcat(fileName,".txt");

  if(check(fileName)){
   FILE* check = fopen(fileName,"r");

   pthread_t email, password;
   
   // if check == NULL means the file has not been open
   if(check == NULL) return false;
   
   struct arg* temp1 = (struct arg* )malloc(sizeof(struct arg));
   struct arg* temp2 = (struct arg* )malloc(sizeof(struct arg));
   char treturn1[10];
   char* treturn2;
   // set the data of the 2 member of struct created 
   set_struct_data(temp1,check,2);
   set_struct_data(temp2,check,4);
   printf("set succes\n");

   // create 2 thread functions 
   pthread_create(&email, NULL, &read_line,(void*)temp1);
   pthread_create(&password, NULL, &read_line,(void*)temp2);
   // wait the thread to return the values
   pthread_join(email,(void**)&treturn1);
   pthread_join(password,(void**)&treturn2);
  
   free(temp1);
   printf("free 1 succces\n");
   free(temp2);
   printf("free 2 succes\n");
   fclose(check);
   return true;
  }
  return false; 
}

and this is the argument of the thread function:

struct arg{
    FILE *file_name;
    int line;
    struct arg* next;
};

is the problem from reading or from pthread_join() ?

  • You're returning a pointer to a stack allocated buffer. Don't do that. – janneb Jun 04 '22 at 12:37
  • What janneb means is, `buffer` is a _local variable_ in your `read_file()` function, and the function returns a pointer to it. Never, _ever_ return a pointer to a local variable. Probably the best way to fix that problem would be to make `buffer` a member of `struct arg`. But,... – Solomon Slow Jun 04 '22 at 13:05
  • Or malloc the buffer. Now it's in the heap instead of on the stack. – Robert Harvey Jun 04 '22 at 13:09
  • ...Why create multiple threads to sequentially read from the same file? What problem will that solve that a single thread could not do better? – Solomon Slow Jun 04 '22 at 13:13
  • @janneb yeah yeah I edit that mistake it's not on the real code – Hocine Abderrahmane Jun 04 '22 at 15:29
  • @SolomonSlow But the function called twice at the same time if I put the buffer as a struct member I need to put buffer1 and buffer2 and add if conditions in the thread function because each call read a specific line not the same line – Hocine Abderrahmane Jun 04 '22 at 15:32
  • @RobertHarvey I edit that mistake not the buffer will be returned char* return_str is the return – Hocine Abderrahmane Jun 04 '22 at 15:33
  • I need to read 2 different lines from the same file that's why I create 2 threads the first read line and second read another line and each thread return a string to call another function and pass the 2 lines as parametres – Hocine Abderrahmane Jun 04 '22 at 15:39
  • See: [why is while feof always wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) While bad for single thread/process case, it produces a _race condition_ when reading the same stream in multiple threads. Change your loop to: `while (fgets(buffer, sizeof(buffer), current->file_name) != NULL) { if (current_line++ == current->line) pthread_exit((void *) buffer); // return the string }` – Craig Estey Jun 04 '22 at 16:24
  • For this use case, the threads can _not_ share the same file stream. They must each have a separate/unique one (i.e. there must be _two_ `fopen` calls). With just one stream, there is a race condition for reading the data. Both threads _share_ the same file stream, so they _interfere_ with one another. – Craig Estey Jun 04 '22 at 16:46
  • Let's say the file has 30 lines. We have two threads Ta and Tb. Ta wants line 7 and Tb wants line 13. Although the threads _could_ intersperse their reads, usually one will go first or the other. If Ta goes first, it _will_ find line 7 correctly. But, it will leave the stream there. Then, Tb runs. It will read 13 lines. Not knowing that it started at line 7, Tb will actually stop at line 20 instead of 13. If Tb goes first, it will get line 13 correctly, but Ta will stop at line 20 (instead of 7). If the threads intersperse their reads, then neither thread will get the line it wants. – Craig Estey Jun 04 '22 at 16:51
  • Re, "...the function called twice at the same time..." You already create two separate instances of `struct arg` and you give one of those to each of the two `read_line()` invocations. So, that means, each `read_line()` would have its own separate `current->buffer` in which to return the string that it finds. – Solomon Slow Jun 04 '22 at 20:05

0 Answers0