下面是尝试编写基本的多线程程序,其中每个线程将从日志文件读取一行(并且什么都不做)。某处有一个bug并且程序段错误(没有生成核心文件)。
如果fgets()
中fscanf()
替换为readInput()
,我会看到核心文件。 Backtrace不一致,并在不同的核心文件中提供不同的调用堆栈。
日志文件的内容如下:
<num> hello<num>
所有小于100的数字
日志文件中有大约90个条目。
AFAIK,对于这段代码的作用,我们不需要锁。但我把它放在以后使用(和练习)。
有人可以在此代码中指出我的错误吗?
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。
#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:感谢您的所有反馈。我希望在原帖中保持实际代码简洁。但这里是.c
和.h
文件以及我正在使用的Makefile
。
EDIT2:添加核心的回溯。 add.c中的第46行是pthread_create()例程。
答案 0 :(得分:1)
问题在于fopen
。代码正确编译,链接和创建可执行文件。运行它时,无法打开日志文件,因为它无法找到它。我有下面的文件/目录结构。 @self的评论帮助确定了问题。
src/
| Makefile
+--include/
| | threads.h
|
+--src/
| add.c
| test.c
| logs.txt
以下任一项都可以解决此问题:(a)更改make规则以在src
目录中构建可执行文件并运行该目录。 (b)按原样保留制定规则,但将fopen
更改为指向src/logs.txt
。