线程在随机位置随机时间后停止运行,没有任何错误

Posted

技术标签:

【中文标题】线程在随机位置随机时间后停止运行,没有任何错误【英文标题】:Thread stops running after random time at random position without any error 【发布时间】:2017-09-06 13:16:16 【问题描述】:

我有一个线程将图像作为原始数据转储到磁盘。它可以正常工作几分钟,然后突然停止执行任何操作。

通过命令行输出,我发现它在循环中的随机位置停止。

程序不会在这个线程中崩溃(它在线程停止运行后不久崩溃,因为我的图像缓冲区已满),所以线程中没有错误/异常/任何东西。

这是我的代码草图:

class ImageWriter

public:
  // constructor, destructor
  void continueWriting();
private:
  void writeImages();
  std::thread m_WriterThread;
  bool m_WriterThreadRunning;
  std::mutex m_ThreadRunningMutex;
  ImageManager * m_ImageManager;
;

ImageWriter::continueWriting()

  // whenever a new image is acquired, this function is called
  // so if the thread has finished, it needs to be restarted
  // this function is also used for the first start of writing
  m_ThreadRunningMutex.lock();
  if ( m_WriterThreadRunning )
  
    m_ThreadRunningMutex.unlock();
  
  else
  
    m_ThreadRunningMutex.unlock();
    if( m_WriterThread.joinable() )
    
      m_WriterThread.join();
    
    m_WriterThreadRunning = true;
    m_WriterThread = std::thread( &ImageWriter::writeImages, this );
  


void ImageWriter::writeImages()

  while ( true )
  
    // MyImage is a struct that contains the image pointer and some metadata
    std::shared_ptr< MyImage > imgPtr = m_ImageManager->getNextImage(m_uiCamId);
    if( imgPtr == nullptr )
    
      // this tells the ImageWriter that currently there are no further images queued
      break;
    

    // check whether the image is valid. If it's not, skip this image and continue with the next one
    [...]

    // create filename
    std::stringstream cFileNameStr;
    cFileNameStr << [...];
    std::ofstream cRawFile( cFileNameStr.str().c_str(), std::ios::out | std::ios::binary );

    unsigned char * ucDataPtr = imgPtr->cImgPtr;
    if( cRawFile.is_open() )
    
      // calculate file size
      unsigned int uiFileSize = [...];
      cRawFile.write(reinterpret_cast<char*>(ucDataPtr), uiFileSize);
      cRawFile.close();
    

    // dump some metadata into a singleton class for logging
    [...]
  

  m_ThreadRunningMutex.lock();
  m_WriterThreadRunning = false;
  m_ThreadRunningMutex.unlock();

ImageManager 是一个负责图像采集和对采集的图像进行排队的类。它还触发 continueWriting()。 continueWriting() 机制是必要的,因为图像的写入速度可能比获取图像的速度快。

为什么这个线程在随机位置随机停止运行并且没有任何错误?

Valgrind 不会在我的控制范围内产生任何东西。 我尝试设置线程的优先级,但这没有任何区别。 我也尝试了另一个磁盘,但这也没有任何区别。

【问题讨论】:

我不明白你在互斥锁下读了 m_WriterThreadRunning 并写了 false,但写了 true 不受保护?这个互斥锁只是为了保护一个布尔值吗?改用原子。我不会停止/启动线程 - 但会在队列中没有图像时实现一些等待机制,并且 continueWriting 只会向线程发出停止等待的信号。 写入 m_WriterThreadRunning true 发生在旧线程连接之后和新线程启动之前,因此不会发生竞争条件。等待机制是有意义的。我什至没有想到。即使它不能解决问题,它也应该更具可读性,真是个好主意! 症状:1) 多线程。 2) 显式使用互斥锁。 3) 短时间使用后的锁。诊断:排除任何合理怀疑,您处于死锁状态。 如果发生死锁,线程不会停在m_ThreadRunningMutex.lock();吗? 【参考方案1】:

我注意到您立即解锁了两个分支中的线程。由于您所做的只是读取布尔值,因此您可能应该完全避免使用锁。读取通常不是需要同步的操作(除非它有副作用,例如读取流,或者位置被释放等)

请考虑:您永远不会在该 bool 为真之前从该 bool 读取 True 值,并且由于您所做的只是读取,因此您永远不会冒该函数为该 bool 分配不正确值的风险。在您已经加入您的线程之前,您不会在此处为 bool 分配新值。

我假设这里发生的情况是您的代码锁定了互斥锁,并且另一个线程尝试写入它,但由于它被锁定而无法写入。

【讨论】:

以上是关于线程在随机位置随机时间后停止运行,没有任何错误的主要内容,如果未能解决你的问题,请参考以下文章

Discord bot命令随机停止与python一起工作?

PHP-cgi 随机停止工作而没有错误日志

FFMpeg Discordjs Music Bot 在随机时间后随机停止播放音乐

标签按钮后如何从列表中随机选择一个字符串

Spring boot REST服务在一段时间后停止

Photon 2 无法加入随机房间