I need to solve this C threading question - c

i need to read a file which contains interger line called data.txt.i need to create threads and read line by line.if a thread has read a line other threads should skip it and should not read it.one thread for one line.i have tried a code but doesnt give any output
i have created threads in a for loop for lines counts.and passed the current value in the for loop as a parameter to thread function.
#include<stdio.h>
#include<string.h>
#include<pthread.h>
int main(){
int a,b,i;
pthread_mutex_t lock;
int getLineCount(){
FILE *fp;
char ch;
int linesCount=0;
fp=fopen("data.txt","r");
if(fp==NULL)
{
printf("File does not exist!!!\n");
return -1;
}
while((ch=fgetc(fp))!=EOF)
{
if(ch=='\n')
linesCount=linesCount+1;
}
fclose(fp);
return linesCount;
}
void *readLine(void *lineNumb){
printf("%d",5);
int lineN= (*(int *)lineNumb);
pthread_mutex_lock(&lock);
FILE* fp = fopen("data.txt", "r");
char line[256];
int i = 0;
while (fgets(line, sizeof(line), fp)) {
i++;
if(i == lineN)
{
fscanf(fp,"%d%d",&a,&b);
printf("%d \n",a+b);
}
}
fclose(fp);
pthread_mutex_unlock(&lock);
}
int lineCount = getLineCount()+1;
pthread_t tid[lineCount];
for (i = 1; i <= lineCount; i++) {
void *b =&i;
pthread_create(&tid[i], NULL,readLine,(void*)b);
pthread_mutex_destroy(&lock);
}
pthread_join(tid[1] ,NULL);
pthread_join(tid[2] ,NULL);
pthread_join(tid[3] ,NULL);
pthread_join(tid[4] ,NULL);
pthread_join(tid[5] , NULL);
return 0;
}

Related

How to fix a Segmentation Fault in pthread_create call

I am having an issue with my current code. I am working on a project where I am using threads to read a group of files from the terminal and tell how many lines there are in the individual and total grouping of files. My question is that when I run the code I get a core dump and when I run my code through gdb I get a segmentation fault at the pthread_create call. Is it because of my implementation or is it due to something else in my code?
#define NUM_THREADS 12
struct thread_data{
char *thread_id;
int count;
};
struct thread_data thread_data_array[NUM_THREADS];
void* filecount(void * thread_arg){
char thread_id;
int count;
struct thread_data *thread;
thread = (struct thread_data *) thread_arg;
thread_id = *thread->thread_id;
count = thread->count;
FILE *fp = fopen(&thread_id, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open %s\n", thread_id);
exit(-1);
}
for (char c = getc(fp); c != EOF; c = getc(fp))
if (c == '\n')
count++;
fclose(fp);
pthread_exit(NULL);
}
int main(int argc, char *argv[]){
if (argc == 1)
return 0;
pthread_t threads[argc];
int t, total_count, count;
total_count = 0;
for(t=1; t<argc; t++){
thread_data_array[t].thread_id = argv[t];
thread_data_array[t].count = count;
printf("Creating thread for file: %s",thread_data_array[t].thread_id);
///This is the line in question///
pthread_create(&threads[t], NULL,filecount,(void *) &thread_data_array[t]);
printf("File name: %s --- line count: %d", thread_data_array[t].thread_id, total_count);
total_count += thread_data_array[t].count;
}
printf("Total line count: %d", total_count);
pthread_exit(NULL);
}
To summarize some of the comments:
This
char thread_id;
thread_id = *thread->thread_id;
will give you the first character of the filename. So while &thread_id is the correct type (char *) for the first argument of fopen, its not a pointer to a null terminating string. This is undefined behaviour.
In
thread_data_array[t].count = count;
count is uninitialized, and its value is indeterminate. This is undefined behaviour.
You need to wait for each thread to finish before you use its result. pthread_join is the function to use here.
getc (fgetc) returns type int, which allows for the check against EOF. Narrowing to char removes the ability to properly test for EOF.
thread_data_array should match the threads array in size.
Here is a refactored program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
struct thread_data {
char *thread_id;
int count;
};
void *filecount(void *thread_arg){
struct thread_data *arg = thread_arg;
FILE *fp = fopen(arg->thread_id, "r");
if (fp == NULL) {
fprintf(stderr, "Cannot open %s\n", arg->thread_id);
pthread_exit(NULL);
}
for (int c = getc(fp); c != EOF; c = getc(fp))
if (c == '\n')
arg->count++;
fclose(fp);
return NULL;
}
int main(int argc, char *argv[]){
if (argc == 1)
return 0;
argv++;
argc--;
pthread_t threads[argc];
struct thread_data thread_data_array[argc];
int total_count = 0;
for (int i = 0; i < argc; i++) {
thread_data_array[i].thread_id = argv[i];
thread_data_array[i].count = 0;
pthread_create(&threads[i], NULL, filecount,(void *) &thread_data_array[i]);
}
for (int i = 0; i < argc; i++) {
pthread_join(threads[i], NULL);
total_count += thread_data_array[i].count;
}
printf("Total line count: %d\n", total_count);
}

Handling file reading in c

I'm having a problem with this program. I'm trying to send the pointer to the beginning of a file. It usually works but, when I send the file from one function to another, then fgets gets and empty string rather than the first row in the file.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int checkf(FILE *file, char*id){
char row[255];
int line_num = 1;
int find_result = 0;
char temp[255];
while (fgets(temp, 255, file) != NULL){ // here i get an Empty 'temp'
// so the contition is always false
if((strstr(temp, id)) != NULL) {
rewind(file);
for (int i=1; i<(line_num-1); i++) {
fgets(row, 255, file);
}
for (int i=0; i<4; i++) {
fgets(row, 255, file);
choppy(row);
printf("%s",row);
if (i!=3) {
printf(" ");
}
}
find_result++;
}
line_num++;
}
return find_result;
}
void add(FILE *file, char fileName[20]){
int check;
char name[100], id[100] ;
scanf("%s",name);
scanf("%s",id);
check = checkf(file,id);
if(check==0){
fputs("\n",file);
fputs(name,file);
}
}
int main(int argc, char * argv[]) {
// insert code here...
FILE *file;
FILE *file_app;
file_app= fopen(argv[argc-1], "a");
file= fopen(argv[argc-1],"r");
//check the there is a file
if (file== NULL)
{
printf("Can't open file");
return 1;
}
else
{
int cmd= strcmp(argv[1],"add");
if (cmd==0) add(file_app,argv[2]);
fclose(file);
printf("\n");
return 0;
}
}
So in conclusion, I think that when I the function checkf() is called from function add(), the file pointer gets lost. But, when I use checks() directly it works. Any ideas?

Trying to read from a file that I know exists and is good but will not open

When I try to open a file "canbus.txt.txt" it is coming back with an error message that reads out "error: No error" repeatedly. I cannot find where this issue would be coming from. My file is in the main project directory and the name and extensions are all correct.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int i;
char value;
char test[60];
char *line;
int num = 0;
int address[25];
int values[25];
void ms_delay (int N)
{
T1CON = 0x08030;
int delay = N * 62.5; // 1 Milisecond => .001 / (256 * (1/16,000,000)) = 62.5
TMR1 = 0;
while (TMR1 < delay);
}
int main (void)
{
PIN_MANAGER_Initialize();
UART1_Initialize();
ECAN1_Initialize();
ECAN1_ReceiveEnable();
INTERRUPT_Initialize();
FILE *fp;
char* filename = "canbus.txt.txt";
fp = fopen(filename, "r");
if(fp == NULL){
perror("Error");
exit(EXIT_FAILURE);
}
while(fgets(line, sizeof(line), fp)){
fscanf(fp, "%lf %lf", &address[num], &values[num]);
sprintf(test, "Value = %lf Other = %lf", address[num], values[num]);
int i = 0;
while(test[i] != '\0'){
UART1_Write(test[i]);
i++;
}
++num;
}
ms_delay(250);
UART1_Write(0x0D);
UART1_Write(0x0A);
fclose(fp);
return 0;
}
#include <stdio.h>
int main()
{
FILE *fr;
char c;
fr = fopen("prog.txt", "r");
while( c != EOF)
{
c = fgetc(fr); /* read from file*/
printf("%c",c); /* display on screen*/
}
fclose(fr);
return 0;
}
To know more https://www.codesdope.com/c-enjoy-with-files/

Unexpected Segfault - What am I doing wrong

I've been trying to blow the cobwebs off my C programming skills, and I've been getting an error I can't seem to figure out. This program reads in a list of integers separated by newlines. This bit happens in read_integer_file... I have no issues going through the input there. It's when I pass the data back to main via out that I have the problem.
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int* out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%i\n");
num_lines++;
}
/* seek to the beginning of the file*/
rewind(file);
out = malloc(sizeof(int)*num_lines);
if(out == NULL)
return 0;
int inp = 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%i\n", &inp);
out[i] = inp;
printf("%i\n", out[i]); /* <---- Prints fine here! */
i++;
}
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int* numbers = NULL;
int number_count = read_integer_file(array_filename, numbers);
for(int i = 0; i < number_count; i++)
{
/* Segfault HERE */
printf("%i\n", numbers[i]);
}
}
You have not allocated any memory for numbers. Currently it is pointing to no where. When it gets back to the calling function it is still pointed to nowhere. Pass a pointer to a pointer to the function to allocate it within the function.
int read_integer_file(char* filename, int** out)
{
...
*out = malloc(sizeof(int)*num_lines);
...
int number_count = read_integer_file(array_filename, &numbers);
This is a version of your code working.. Keep in mind also that fscanf just skip the \n the way you wrote it so it's like writing fscanf(file, "%d");
And if you don't put a variable to handle what it reads the compiler may not see it but you'll probably get an error..
So here is the code :
#include <stdlib.h>
#include <stdio.h>
int read_integer_file(char* filename, int **out)
{
FILE* file;
file = fopen(filename, "r");
/* check if the file open was successful */
if(file == NULL)
{
return 0;
}
int num_lines = 0;
int garbi;
char garbc;
/* first check how many lines there are in the file */
while(!feof(file))
{
fscanf(file, "%d", &garbi);
fscanf(file, "%c", &garbc);
if (garbc=='\n') ++num_lines;
}
/* seek to the beginning of the file*/
rewind(file);
int *nbr = malloc(sizeof(int)*num_lines);
if(nbr == NULL)
return 0;
int i = 0;
while(!feof(file))
{
fscanf(file, "%d", &nbr[i++]);
fscanf(file, "%c", &garbc);
}
*out=nbr;
return num_lines;
}
int main(int argc, char** argv)
{
if(argc < 2)
{
printf("Not enough arguments!");
return -1;
}
/* get the input filename from the command line */
char* array_filename = argv[1];
int *numbers = NULL;
int number_count = read_integer_file(array_filename, &numbers);
int i;
for(i = 0; i < number_count; ++i)
printf("%d\n", numbers[i]);
return 0;
}

run pthreads from pthread

I have a file which contains a list of filenames in which I wanna search for a word and replace it
I modified the code a little just to show only relevant parts here
The problem is that if I have only one file in that list, it won't process it with multi threads because the threads are working only if I have multiple files
So I want to keep the current threads configuration but I wanna add some threads at the processing part
I have this code:
struct words_list {
char word[20];
struct words_list * next;
};
FILE * INFILE;
int num_thread = 10;
// Mutex variables
pthread_mutex_t input_queue;
pthread_mutex_t word_list;
int main(int argc,char **argv)
{
//some code is missing
if((INFILE = fopen(myfile,"r")) == NULL) {
fprintf(stderr,"Can't open input file\n");
exit(0);
}
for(i = 0 ; i < number_thread; i++)
{
if(pthread_create(&thread_id[i],NULL,&search,NULL) != 0)
{
i--;
fprintf(stderr,RED "\nError in creating thread\n" NONE);
}
}
for(i = 0 ; i < number_thread; i++)
if(pthread_join(thread_id[i],NULL) != 0)
{
fprintf(stderr,RED "\nError in joining thread\n" NONE);
}
fflush(INFILE);
fclose(INFILE);
}
void * search(void * data)
{
char file[20];
while (!feof(INFILE))
{
if (fgets(file,sizeof(file),INFILE) != NULL)
{
if (strlen(file) < 8)
break;
if (file[strlen (file) - 1] == '\n')
file[strlen (file) - 1] = '\0';
}
process(file);
}
return NULL;
}
void process(char *filename)
{
char buff[512];
char word[20];
struct words_list * curr_word = first_word;
if(verbose != 0)
fprintf(stderr,"Processing: %s\n",filename);
while(curr_word != NULL)
{
//some code missing
pthread_mutex_lock(&word_list);
strncpy(word,curr_word->word,sizeof(word) - 1);
pthread_mutex_unlock(&word_list);
**//replace_word must run with multiple threads**
ret = replace_word(word,buff,sizeof(buff));
//end of threads part
//code missing
}
}
How can I add other pthreads at the bold part so it can process with multiple threads each file?
Instead of assigning one thread per file. Why shouldn't you allocate a thread to process portion of each file. As shown below, I allocated a thread for every 50 bytes of data in a file. In this technique, even if you have only one file in the list, you can still use multiple threads to parse it. Hope it helps.
#include "stdio.h"
#include "pthread.h"
#include "sys/stat.h"
#include "string.h"
#include "fcntl.h"
#define TOTAL_NUMBER_THREADS 100
struct words_list {
char word[20];
struct words_list * next;
};
struct file_segment {
char filename[50];
size_t foffset;
size_t size;
}fs[TOTAL_NUMBER_THREADS];
FILE * INFILE;
int num_thread=0;
// Mutex variables
pthread_mutex_t input_queue;
pthread_mutex_t word_list;
pthread_t thread_id[TOTAL_NUMBER_THREADS];
void *process( void *arg);
void segment_file(char *filename)
{
int fd;
int offset=0;
struct stat statbuf;
size_t size;
fd = open(filename, O_RDONLY);
if(fd < 0)
{
perror("fopen");
return;
}
fstat(fd, &statbuf);
size=statbuf.st_size;
while((offset < size) && (num_thread <= 100))
{
strncpy(fs[num_thread].filename, filename, sizeof(fs[num_thread].filename));
fs[num_thread].foffset=offset;
fs[num_thread].size=(size>50)?50:size;
offset+=fs[num_thread].size;
if(pthread_create(&thread_id[num_thread],NULL,&process,&fs[num_thread]) != 0)
{
fprintf(stderr,"\nError in creating thread\n");
}
num_thread++;
}
return;
}
void *process( void *arg)
{
char buf[50];
struct file_segment *fs;
char word[20];
//struct words_list * curr_word = first_word;
fs = (struct file_segment *) arg;
FILE *fp;
fp=fopen(fs->filename, "r");
fseek(fp, fs->foffset, SEEK_SET);
fread(buf,1,fs->size,fp);
while(curr_word != NULL)
{
//some code missing
pthread_mutex_lock(&word_list);
strncpy(word,curr_word->word,sizeof(word) - 1);
pthread_mutex_unlock(&word_list);
**//replace_word must run with multiple threads**
ret = replace_word(word,buff,sizeof(buff));
//end of threads part
//code missing
}
//printf("Filename: %s\n Info: %s\n", fs->filename, buf);
printf("%s", buf);
return;
}
int main(int argc,char **argv)
{
//some code is missing
char file[50];
int i;
if((INFILE = fopen("list.txt","r")) == NULL) {
fprintf(stderr,"Can't open input file\n");
return 0; }
while (!feof(INFILE))
{
if (fgets(file,sizeof(file),INFILE) != NULL)
{
if (strlen(file) < 8)
break;
if (file[strlen (file) - 1] == '\n')
file[strlen (file) - 1] = '\0';
}
segment_file(file);
}
for(i = 0 ; i < num_thread; i++)
if(pthread_join(thread_id[i],NULL) != 0)
{
fprintf(stderr,"\nError in joining thread\n");
}
fflush(INFILE);
fclose(INFILE);
}

Resources