이미지를 디스크에 원시 데이터로 덤프하는 스레드가 있습니다. 그것은 몇 분 동안 잘 작동하고 갑자기 아무것도하는 것을 멈 춥니 다.스레드가 임의의 시간에 아무런 오류없이 임의의 위치에서 실행 중지
명령 줄 출력을 통해 루프 내의 임의의 위치에서 멈추는 것을 발견했습니다.
이 프로그램은 스레드에서 이렇게 에러/예외/무엇을 (내 이미지 버퍼가 가득 차면 때문에 스레드가 실행되지 중지 직후 충돌)이 thread 내에서 충돌하지 않습니다.
여기 내 코드의 스케치입니다 :
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을 읽고 뮤텍스 잠금에서 거짓 쓸 수 있지만 진정한 보호되지 않은 쓰기 이해하지? 이 뮤텍스는 오직 하나의 부울을 보호하기위한 것입니까? 대신 원자를 사용하십시오. 스레드를 시작/중지하지는 않겠지 만 이미지가 대기열에 없으면 continueWriting이 스레드에 대기 신호를 보냅니다. –
m_WriterThreadRunning 쓰기는 이전 스레드가 연결되고 새 스레드가 시작되기 전에 발생하므로 어떤 경쟁 조건도 발생할 수 없습니다. 대기 메커니즘이 적합합니다. 나에게 일어나지도 않았다. 문제가 해결되지 않아도 읽을 수 있어야하므로 좋은 생각입니다! –
증상 : 1) 다중 스레드. 2) 명시 적 뮤텍스 사용. 3) 잠시 사용 후 잠급니다. 진단 : 합리적인 의심의 여지없이 교착 상태가 발생합니다. –