views:

176

answers:

4

Hi all,

I have a thread to monitor serial port using select system call, the run function of the thread is as follows:

void <ProtocolClass>::run()
{
    int fd = mPort->GetFileDescriptor();
    fd_set readfs;
    int maxfd=fd+1;
    int res;

    struct timeval Timeout;
    Timeout.tv_usec=0;
    Timeout.tv_sec=3;


   //BYTE  ack_message_frame[ACKNOWLEDGE_FRAME_SIZE];
   while(true)
   {
        usleep(10);
        FD_ZERO(&readfs);
        FD_SET(fd,&readfs); 
        res=select(maxfd,&readfs,NULL,NULL,NULL);
        if(res<0)
           perror("\nselect failed");
        else if( res==0)
                        puts("TIMEOUT");
        else if(FD_ISSET(fd,&readfs))
        {//IF INPUT RECEIVED
                qDebug("************RECEIVED DATA****************");
        FlushBuf();
        qDebug("\nReading data into a read buffer");
        int bytes_read=mPort->ReadPort(mBuf,1000);
        mFrameReceived=false;
        for(int i=0;i<bytes_read;i++)
        {
            qDebug("%x",mBuf[i]);
        }



        //if complete frame has been received, write the acknowledge message frame to the port.
        if(bytes_read>0)
        {
                qDebug("\nAbout to Process Received bytes");
            ProcessReceivedBytes(mBuf,bytes_read);
            qDebug("\n Processed Received bytes");
            if(mFrameReceived)
        {
        int no_bytes=mPort->WritePort(mAcknowledgeMessage,ACKNOWLEDGE_FRAME_SIZE);
            }//if frame received
        }//if bytes read > 0
        } //if input received
    }//end while
}

The problem is when I exit from this thread, using

delete <protocolclass>::instance();

the program crashes with a glibc error of malloc memory corruption. On checking the core with gdb it was found the when exiting the thread it was processing the data and thus the error. The destructor of the protocol class looks as follows:

<ProtocolClass>::~<ProtocolClass>()
{
   delete [] mpTrackInfo; //delete data
   wait();
   mPort->ClosePort();
   s_instance = NULL;  //static instance of singleton
   delete mPort;
}

Is this due to select? Do the semantics for destroying objects change when select is involved? Can someone suggest a clean way to destroy threads involving select call.

Thanks

A: 

Are the threads still looking at mpTrackInfo after you delete it?

Not seeing the code it is hard.
But Iwould think that the first thing the destructor should do is wait for any threads to die (preferably with some form of join() to make sure they are all accounted for). Once they are dead you can start cleaning up the data.

Martin York
+3  A: 

I'm not sure what threading library you use, but you should probably signal the thread in one way or another that it should exit, rather than killing it.

The most simple way would be to keep a boolean that is set true when the thread should exit, and use a timeout on the select() call to check it periodically.

ProtocolClass::StopThread ()
{
  kill_me = true;

  // Wait for thread to die
  Join();
}

ProtocolClass::run ()
{
  struct timeval tv;
  ...
  while (!kill_me) {
    ...
    tv.tv_sec = 1;
    tv.tv_usec = 0;
    res = select (maxfd, &readfds, NULL, NULL, &tv);

    if (res < 0) {
      // Handle error
    }

    else if (res != 0) {
      ...
    }
}

You could also set up a pipe and include it in readfds, and then just write something to it from another thread. That would avoid waking up every second and bring down the thread without delay.

Also, you should of course never use a boolean variable like that without some kind of lock, ...

Jonatan
Nice general way. Make sure to clean up before returning so the calling thread just has to stop the thread.
stefaanv
I have read about the pipe thing and successfully implemented it now. The wait condition solution you suggested was earlier being used in my application but I wanted to avoid handling any synchronisation issues because of which I had changed the implementation in the first place.
rocknroll
A: 

your thread is more than just memory with some members, so just deleting and counting on the destructor is not enough. Since I don't know qt threads I think this link can put you on your way: trolltech message

stefaanv
A: 

Two possible problems:

  • What is mpTrackInfo? You delete it before you wait for the thread to exit. Does the thread use this data somewhere, maybe even after it's been deleted?
  • How does the thread know it's supposed to exit? The loop in run() seems to run forever, which should cause wait() in the destructor to wait forever.
sth
mpTrackInfo is an object array which holds the relevant data. I have changed its placement after wait() statement and it isn't crashing now. wait(10) statement gives a timeout of 10 usec and on timeout returns from run() function. But it still is a forced destruction, I will use pipe method now.
rocknroll