用select()系统调用语句关闭一个线程?

时间:2009-07-01 06:44:17

标签: c++ multithreading qt

我有一个使用select系统调用监视串口的线程,该线程的run函数如下:

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
}

问题是当我从这个线程退出时,使用

delete <protocolclass>::instance();

程序因malloc内存损坏的glibc错误而崩溃。在使用gdb检查核心时,发现退出线程时它正在处理数据,从而导致错误。协议类的析构函数如下所示:

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

这是选择吗?当涉及select时,销毁对象的语义是否会发生变化?有人可以建议一种干净的方法来销毁涉及选择呼叫的线程。

由于

4 个答案:

答案 0 :(得分:3)

我不确定你使用的是哪个线程库,但是你应该以某种方式发出它应该退出的信号,而不是杀死它。

最简单的方法是保留一个在线程退出时设置为true的布尔值,并在select()调用上使用超时来定期检查它。

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) {
      ...
    }
}

您还可以设置一个管道并将其包含在readfds中,然后从另一个线程中写入一些内容。这样可以避免每秒唤醒并立即打倒线程。

此外,如果没有某种锁定,你当然不应该使用类似的布尔变量,......

答案 1 :(得分:0)

删除后,线程是否仍在查看mpTrackInfo?

没有看到代码很难。
但是我认为析构函数应该做的第一件事就是等待任何线程死掉(最好用某种形式的join()来确保它们都被占用)。一旦它们死了,你就可以开始清理数据了。

答案 2 :(得分:0)

你的线程不仅仅是一些成员的内存,所以只删除和计算析构函数是不够的。由于我不知道qt线程,我认为这个链接可以帮助你: trolltech message

答案 3 :(得分:0)

两个可能的问题:

  • 什么是mpTrackInfo?在等待线程退出之前删除它。线程是否在某处使用了这些数据,甚至可能在它被删除后?
  • 线程如何知道它应该退出? run()中的循环似乎永远运行,这会导致析构函数中的wait()永远等待。