J'ai un thread qui stocke des images en tant que données brutes sur le disque. Cela fonctionne bien pendant quelques minutes et soudainement, il cesse de faire quoi que ce soit. Par la sortie de la ligne de commande, j'ai trouvé qu'il s'arrêtait à des positions aléatoires dans la boucle.Les threads s'arrêtent après un temps aléatoire à une position aléatoire sans aucune erreur
Le programme ne plante pas dans ce thread (il se bloque peu de temps après l'arrêt du thread car mon tampon d'image est plein), donc pas d'erreur/exception/rien du thread.
est ici un croquis de mon code:
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 est une classe qui prend en charge l'acquisition d'images et des files d'attente les images acquises. Il déclenche également continueWriting(). Le mécanisme continueWriting() est nécessaire, car les images peuvent être écrites plus vite qu'elles ne sont acquises.
Pourquoi ce thread s'arrête-t-il de fonctionner à des moments aléatoires à des positions aléatoires et sans aucune erreur? Valgrind ne cède rien sous mon contrôle. J'ai essayé de régler la priorité du fil, mais cela n'a fait aucune différence. J'ai aussi essayé un autre disque, mais cela ne faisait pas de différence non plus.
Je ne comprends pas que vous lisez m_WriterThreadRunning et écrivez false sous mutex lock, mais écrire true non protégé? Ce mutex est-il seulement pour protéger un booléen? utilisez atomique à la place. Je ne voudrais pas arrêter/démarrer les threads - mais implémenter un mécanisme d'attente quand aucune image ne se trouve dans la file d'attente et que continueWriting ne fera que signaler au thread d'arrêter d'attendre. –
Écrire m_WriterThreadRunning true se produit après que l'ancien thread est joint et avant que le nouveau ne soit démarré, donc aucune condition de concurrence ne peut s'y produire. Le mécanisme d'attente a du sens. Je ne me suis même pas présenté. Même si cela ne résout pas le problème, il devrait être plus lisible, donc bonne idée! –
Symptômes: 1) multithread. 2) l'utilisation explicite de mutex. 3) se verrouille après une courte période d'utilisation. Diagnostic: au-delà de tout doute raisonnable, vous avez une situation de blocage. –