Bhaskar
Bhaskar

Reputation: 2733

Simple multithreaded program segfault

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

Answers (1)

Bhaskar
Bhaskar

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

Related Questions