0

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;
    }
2
  • 1
    What makes you think you need to use a std::auto_ptr? Commented Sep 12, 2015 at 8:00
  • Wrappers around wrappers. Very convoluted. Commented Sep 12, 2015 at 8:08

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks @Alan, You saved my day and several hour of frustration. i was just not able to figure it out. i wanted to use c++11 thread and i did as well then people here wanted pthread only and then i needed to write whole code again. Code was failing and hence i written a sample code to test my things. Regarding auto_ptr, i though it will be better that a plain pointer. am i wrong here? Can you elaborate a bit? thanks in advance.
Hello @Alan, thanks for your answer again. I understood the problem.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.