I have created a wrapper class with two threads for a serial line based interface. I ended up seeing Segmentation errors about once every 10 to 20 times of stopping and starting threads again in a single instance of the interface.
I wrote a simpler wrapper for a thread and still see issue. I am including a sample code that I have been testing. I wrote a class that could start and stop a single thread. I also tried a few variations with pthread_join and without. What I find, is that my system hangs at the time of stopping the thread. I have observed the same with my serial driver wrapper. I am curious, if I am missing or making an error in handling the thread.
The errors I receive always come, as the thread or threads are being terminated. I get Segmentation error and also a pthread_mutex error in my serial driver. In this example, I see a hang.
Compiler
Code:
roman@the777 ~ $ gcc -v
Using built-in specs.
Target: i686-pc-linux-gnu
Configured with: /var/tmp/portage/sys-devel/gcc-4.1.2/work/gcc-4.1.2/configure --prefix=/usr --bindir=/usr/i686-pc-linux-gnu/gcc-bin/4.1.2 --includedir=/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include --datadir=/usr/share/gcc-data/i686-pc-linux-gnu/4.1.2 --mandir=/usr/share/gcc-data/i686-pc-linux-gnu/4.1.2/man --infodir=/usr/share/gcc-data/i686-pc-linux-gnu/4.1.2/info --with-gxx-include-dir=/usr/lib/gcc/i686-pc-linux-gnu/4.1.2/include/g++-v4 --host=i686-pc-linux-gnu --build=i686-pc-linux-gnu --disable-altivec --enable-nls --without-included-gettext --with-system-zlib --disable-checking --disable-werror --enable-secureplt --disable-multilib --enable-libmudflap --disable-libssp --disable-libgcj --with-arch=i686 --enable-languages=c,c++,treelang,fortran --enable-shared --enable-threads=posix --enable-__cxa_atexit --enable-clocale=gnu
Thread model: posix
gcc version 4.1.2 (Gentoo 4.1.2 p1.3)
Here is the code:
Code:
/**
* thread_attempts.cpp
*
**/
#include<stdlib.h>
#include <pthread.h>
#include <stddef.h>
#include <unistd.h>
#include <errno.h>
#include <signal.h>
#include <queue>
#include <string.h>
#include <stdio.h>
class ThreadAttempt
{
private:
static void * thread_init(void *arg);
pthread_t thread;
int thread_function();
void start_thread();
void stop_thread();
pthread_mutex_t data_access_mutex;
bool thread_started;
bool thread_alive;
bool thread_needs_to_exit;
int thread_run_counter;
public:
ThreadAttempt();
~ThreadAttempt();
void start();
void stop();
int count();
};
ThreadAttempt::ThreadAttempt()
{
printf("initialized the trial\n");fflush(stdout);
thread_started = false;
thread_alive = false;
thread_needs_to_exit = false;
thread_run_counter = 0;
pthread_mutex_init(&data_access_mutex, NULL);
}
ThreadAttempt::~ThreadAttempt()
{
stop();
pthread_mutex_destroy(&data_access_mutex);
printf("destoyed...\n");fflush(stdout);
}
void ThreadAttempt::start()
{
bool clear_to_start = true;
int count = 0;
pthread_mutex_lock(&data_access_mutex);
if( thread_started || thread_alive ) clear_to_start = false;
pthread_mutex_unlock(&data_access_mutex);
if( clear_to_start )
{
pthread_mutex_lock(&data_access_mutex);
thread_started = true;
thread_alive = true;
thread_needs_to_exit = false;
thread_run_counter += 1;
count = thread_run_counter;
pthread_mutex_unlock(&data_access_mutex);
pthread_create(&thread, NULL, &thread_init, (void *) this);
printf("started the thread - attempt number %d\n", count);fflush(stdout);
}
}
void ThreadAttempt::stop()
{
bool clear_to_stop = false;
bool alive = true;
int count = 0;
pthread_mutex_lock(&data_access_mutex);
if( thread_started && thread_alive ) clear_to_stop = true;
pthread_mutex_unlock(&data_access_mutex);
if( clear_to_stop )
{
pthread_mutex_lock(&data_access_mutex);
thread_needs_to_exit = true;
pthread_mutex_unlock(&data_access_mutex);
while( alive==true )
{
// usleep(1000000); // one sec
pthread_mutex_lock(&data_access_mutex);
alive = thread_alive;
count = thread_run_counter;
pthread_mutex_unlock(&data_access_mutex);
}
printf("stopped the thread - attempt number %d\n", count);fflush(stdout);
pthread_mutex_lock(&data_access_mutex);
thread_started = false;
thread_alive = false;
thread_needs_to_exit = false;
pthread_mutex_unlock(&data_access_mutex);
}
}
int ThreadAttempt::count()
{
int tmp=0;
pthread_mutex_lock(&data_access_mutex);
tmp = thread_run_counter;
pthread_mutex_unlock(&data_access_mutex);
return tmp;
}
void *ThreadAttempt::thread_init(void *arg){ ((ThreadAttempt *) arg)->thread_function(); }
int ThreadAttempt::thread_function()
{
bool run_flag = true;
bool tick = true;
while( run_flag )
{
pthread_mutex_lock(&data_access_mutex);
if( thread_needs_to_exit ) run_flag = false;
pthread_mutex_unlock(&data_access_mutex);
// usleep((int)(0.01*1000000));
// if( tick ) { tick=false; printf("tick "); fflush(stdout); }
// else { tick=true; printf("tock "); fflush(stdout); }
}
printf("\n"); fflush(stdout);
pthread_mutex_lock(&data_access_mutex);
thread_started = false;
thread_alive = false;
thread_needs_to_exit = false;
pthread_mutex_unlock(&data_access_mutex);
pthread_exit(NULL);
}
int main(void)
{
ThreadAttempt *trial = new ThreadAttempt();
int countdown = 1000000;
while( countdown )
{
trial->start();
usleep((int)(0.1*1000000));
trial->stop();
countdown-=1;
}
return 0;
}
Makefile
Code:
all: thread_trial
CPPFLAGS = -x c++ -O0 -c
CFLAGS = -x c -O0
# add -v for verbose
# add -pthread for thread support
LFLAGS = -static -O0 -pthread
CC = g++
thread_attempts.o: thread_attempts.cpp
$(CC) $(CPPFLAGS) thread_attempts.cpp
thread_trial: thread_attempts.o
$(CC) $(LFLAGS) thread_attempts.o -o example_compiled
clena: clean
claen: clean
celan: clean
clean:
rm -rf ./*.o
rm -f example_compiled
Output
Code:
stopped the thread - attempt number 374
started the thread - attempt number 375
stopped the thread - attempt number 375
started the thread - attempt number 376
stopped the thread - attempt number 376
started the thread - attempt number 377
stopped the thread - attempt number 377
started the thread - attempt number 378
stopped the thread - attempt number 378
started the thread - attempt number 379
stopped the thread - attempt number 379
started the thread - attempt number 380
stopped the thread - attempt number 380
started the thread - attempt number 381
stopped the thread - attempt number 381
started the thread - attempt number 382
stopped the thread - attempt number 382
started the thread - attempt number 383
Top
Code:
top - 06:42:06 up 2 days, 3:18, 1 user, load average: 1.28, 1.47, 1.56
Tasks: 1 total, 1 running, 0 sleeping, 0 stopped, 0 zombie
Cpu(s): 27.8%us, 0.2%sy, 0.0%ni, 71.9%id, 0.0%wa, 0.0%hi, 0.1%si, 0.0%st
Mem: 2072172k total, 992692k used, 1079480k free, 75704k buffers
Swap: 2008116k total, 56028k used, 1952088k free, 611792k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
4349 roman 20 0 3058m 3364 212 R 100 0.2 51:37.78 example_compile
Please advice.....................