Reputation: 2733
Below is an attempt to write basic multi-threaded program where each thread will read one line from a log file (and does nothing). There is a bug somewhere and program segfaults (no core file generated).
If fgets()
is replaced by fscanf()
in readInput()
then I see a core file. Backtrace is inconsistent and gives different call stack in different core file.
Contents of log file look like:
<num> hello<num>
all numbers less than 100
There are about 90 entries in the log file.
AFAIK, for what this code is doing, we don't need locks. But I put it for later use (and practice).
Can someone please point my mistakes in this code?
threads.h
---------
#include "../../include/global.h"
#include <pthread.h>
#define MAX_LOGS 101
#define NUM_THREADS 10
/* a single record in log file. Read by thread from input stream (file) */
typedef struct __thread_data {
int time; /* time stamp */
char log[32]; /* short log msg */
} thread_data_t;
/* heap (implemented by ordered array) storing the logs */
typedef struct __heap {
thread_data_t entry[MAX_LOGS];
int cur_size; /* used while inserting nodes? */
} heap_t;
add.c
-----
#include "../include/threads.h"
/* Stream from which logs are read (file stream here). Only one thread can
* read at a time */
FILE *fp;
pthread_mutex_t fp_lock;
/* thread start routine */
void *readInput(void *arg)
{
char log[40];
/* get lock for file read */
pthread_mutex_lock(&fp_lock);
/* Critical Section; read file */
if(!feof(fp)) {
fgets(log, 40, fp);
}
/* release lock */
pthread_mutex_unlock(&fp_lock);
pthread_exit(NULL);
}
int pthread_main()
{
int i, ret;
pthread_t threads[NUM_THREADS];
pthread_mutex_init(&fp_lock, NULL);
fp = fopen("logs.txt", "r");
/* error check */
for(i=0; i<NUM_THREADS; i++) {
if(ret = pthread_create(&threads[i], NULL, readInput, NULL)) {
printf("Oops: %s\n", strerror(ret));
return EXIT_FAILURE;
}
}
for(i=0; i<NUM_THREADS; i++) {
pthread_join(threads[i], NULL);
}
fclose(fp);
return EXIT_SUCCESS;
}
test.c
-------
#include "../include/threads.h"
int main()
{
return pthread_main();
}
Makefile
---------
CC = gcc
CFLAGS = -pthread
OBJFLAGS = -o
STDFLAGS = -std=c99
DBGS = -ggdb -pthread
OBJS = add.o test.o
HEADERS = include/threads.h
SOURCES = src/add.c src/test.c
all: $(OBJS)
$(CC) $(OBJFLAGS) th $(OBJS)
#make clean
$(OBJS): $(SOURCES) $(HEADERS)
$(CC) -c $(DBGS) $(SOURCES)
.PHONY: clean
clean:
rm -rf *.o
Backtrace of core dump.
#0 0x00007fff88d5b68e in pthread_create ()
(gdb) bt
#0 0x00007fff88d5b68e in pthread_create ()
#1 0x00000001051e0cf8 in pthread_main () at add.c:46
#2 0x00000001051e0dbf in main () at test.c:5
(gdb) list
1 #include "../include/threads.h"
2
3 int main()
4 {
5 pthread_main();
6 return 0;
7 }
(gdb) info thread
error on line 787 of "/SourceCache/gdb/gdb-1824/src/gdb/macosx/macosx-nat-infthread.c" in function "void print_thread_info(thread_t, int *)": (ipc/send) invalid destination port (0x10000003)
(gdb) info threads
5 0x00007fff88d47194 in thread_start ()
4 0x00007fff8a15e122 in __psynch_mutexwait ()
3 0x00007fff8a15e122 in __psynch_mutexwait ()
2 0x00007fff88dc242b in flockfile ()
* 1 0x00007fff88d5b68e in pthread_create ()
EDIT1: Thanks for all your feedback. I wanted to keep the actual code concise in original post. But here are the .c
and .h
files and also the Makefile
I am using.
EDIT2: Adding backtrace of core. Line 46 in add.c is pthread_create() routine.
Upvotes: 2
Views: 430
Reputation: 2733
Problem lies in fopen
. Code compiles, links and creates an executable correctly. When running it, it failed to open the log file as it could not locate it. I have below file/directory structure. Comment made by @self helped identify the issue.
src/
| Makefile
+--include/
| | threads.h
|
+--src/
| add.c
| test.c
| logs.txt
Either one of the following resolves the issue: (a) Changing the make rule to build executable in src
directory and running it that directory. (b) Keep make rule as is but change fopen
to point to src/logs.txt
.
Upvotes: 1