Reputation: 23
I have a such a requirement that:- 1) There are two class, say Wrapper and Wrapper2. 2) Wrapper2 contains reference object of class Wrapper. 3) A thread will write data to a variable of class Wrapper which should be essentially be calling a member function of Wrapper. 4) Another thread can read and write data to class member of Wrapper and this thread essentially be called through Wrapper2.
Based on some answers on older question on Stackoverflow, i created an example code to check why my production code is failing and i am not able to figure out the problem. As soon as thread2 is created it receives SIGSEG signals. Code is below:-
#include <thread>
#include <iostream>
#include <chrono>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>
#include <signal.h>
#include <pthread.h>
#include <wait.h>
#include <string.h>
pthread_mutex_t mt1;
void thread_signal(int signum)
{
pthread_exit(0);
}
void sig_func(int sig)
{
write(1, "Caught signal 11\n", 17);
std::cout<<"Caught signal :"<<sig<<std::endl;
signal(SIGSEGV,sig_func);
thread_signal(sig);
}
class Wrapper {
public:
Wrapper():i(10)
{
std::cout<<"Wrapper Constructor Called. "<<this<<" \n";
}
~Wrapper()
{
std::cout<<"Wrapper Destructor Called. "<<this<<"\n";
}
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
void setI(int i)
{
pthread_mutex_lock(&mt1);
this->i=i;
std::cout<<"set: "<< this->i<<std::endl;
pthread_mutex_unlock(&mt1);
}
int getI()
{
pthread_mutex_lock(&mt1);
std::cout<<"get: "<< this->i<<std::endl;
pthread_mutex_unlock(&mt1);
return 0;
}
int i;
};
class Wrapper2
{
public:
Wrapper2(Wrapper & wp):wp2(wp)
{
std::cout<<"Wrapper2 Constructor Called. "<<this<<" \n";
}
~Wrapper2()
{
std::cout<<"Wrapper2 Destructor Called. "<<this<<" \n";
}
Wrapper & wp2;
};
struct ThreadWrapper {
Wrapper & wr1;
Wrapper2 & wr2;
ThreadWrapper( Wrapper & wr1,Wrapper2& wr2):
wr1(wr1),wr2(wr2)
{
}
};
extern "C" void* wrapper1Fun ( void* wr1)
{
std::auto_ptr< Wrapper > wrp1 ( static_cast< Wrapper* >( wr1 ) );
std::cout<<"Thread 1 created. \n";
while(1)
{
wrp1->setI(rand()%100);
usleep(50);
}
return 0;
}
extern "C" void* wrapper2Fun ( void* wr2)
{
std::auto_ptr< Wrapper2 > wrp2 ( static_cast< Wrapper2* >( wr2 ) );
std::cout<<"Thread 2 created. \n";
while(1)
{
wrp2->wp2.getI();
usleep(50);
}
return 0;
}
int main(int argc, char **argv) {
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sa.sa_handler = thread_signal;
sa.sa_flags = 0;
sigaction(SIGTERM, &sa, 0);
bool mainRunning= true;
Wrapper w;
Wrapper2 w1(w);
sleep(1);
ThreadWrapper * myWrap = new ThreadWrapper(w,w1);
sleep(1);
pthread_t pt1;
pthread_t pt2;
pthread_attr_t attr;
signal(SIGSEGV,sig_func); // Register signal handler before going multithread
pthread_attr_init(&attr);
int i = pthread_create(&pt1, NULL,wrapper1Fun, myWrap);
std::cout<<"First thread status "<<i<<std::endl;
sleep(1);
int j = pthread_create(&pt2, &attr,wrapper2Fun, myWrap);
std::cout<<"Second thread status "<<j<<std::endl;
sleep(1);
while(1);
fprintf(stderr, "kill thread\n");
//pthread_kill(pt1, SIGTERM);
fprintf(stderr, "join thread\n");
pthread_join(pt1, NULL);
pthread_join(pt1, NULL);
return 0;
}
Upvotes: 0
Views: 188
Reputation: 18964
wrapper1Fun
expects to be passed a pointer to a Wrapper
, and wrapper2Fun
expects to be passed a pointer to a Wraper2
. But you're actually passing a pointer to a ThreadWrapper
to each, which is a completely different type, so it goes wrong.
The use of void *
and casts prevents the compiler from pointing out your type error. I would suggest using a type safe C++ threading library rather than raw pthread
. Boost has one, as does the standard library from C++11.
Also your use of auto_ptr
is questionable at best. It's deprecated, easy to get wrong, and a poor way of expressing ownership - prefer unique_ptr
or shared_ptr
.
Here you construct two auto_ptr
values owning the same pointer, so it will be freed twice, which is undefined behaviour.
In any case there's no obvious reason to put any of these objects on the heap. If you do, you need to decide where the ownership of the memory resides.
Upvotes: 3