Fix potential crash in document saving

Probably doesn't happen very often since most of the times people don't save while rendering is still happening
but if that is the case we need to wait for all the rendering to finish otherwise we remove the document
from under the render thread feet and bad things happen
This commit is contained in:
Albert Astals Cid 2018-02-14 17:48:10 +01:00 committed by Albert Astals Cid
parent 83374b97df
commit e8d9feed70
2 changed files with 32 additions and 23 deletions

View file

@ -2118,6 +2118,33 @@ void DocumentPrivate::loadSyncFile( const QString & filePath )
m_pagesVector[i]->setSourceReferences( refRects.at(i) ); m_pagesVector[i]->setSourceReferences( refRects.at(i) );
} }
void DocumentPrivate::clearAndWaitForRequests()
{
m_pixmapRequestsMutex.lock();
QLinkedList< PixmapRequest * >::const_iterator sIt = m_pixmapRequestsStack.constBegin();
QLinkedList< PixmapRequest * >::const_iterator sEnd = m_pixmapRequestsStack.constEnd();
for ( ; sIt != sEnd; ++sIt )
delete *sIt;
m_pixmapRequestsStack.clear();
m_pixmapRequestsMutex.unlock();
QEventLoop loop;
bool startEventLoop = false;
do
{
m_pixmapRequestsMutex.lock();
startEventLoop = !m_executingPixmapRequests.isEmpty();
m_pixmapRequestsMutex.unlock();
if ( startEventLoop )
{
m_closingLoop = &loop;
loop.exec();
m_closingLoop = nullptr;
}
}
while ( startEventLoop );
}
Document::Document( QWidget *widget ) Document::Document( QWidget *widget )
: QObject( nullptr ), d( new DocumentPrivate( this ) ) : QObject( nullptr ), d( new DocumentPrivate( this ) )
{ {
@ -2533,29 +2560,7 @@ void Document::closeDocument()
d->m_scripter = nullptr; d->m_scripter = nullptr;
// remove requests left in queue // remove requests left in queue
d->m_pixmapRequestsMutex.lock(); d->clearAndWaitForRequests();
QLinkedList< PixmapRequest * >::const_iterator sIt = d->m_pixmapRequestsStack.constBegin();
QLinkedList< PixmapRequest * >::const_iterator sEnd = d->m_pixmapRequestsStack.constEnd();
for ( ; sIt != sEnd; ++sIt )
delete *sIt;
d->m_pixmapRequestsStack.clear();
d->m_pixmapRequestsMutex.unlock();
QEventLoop loop;
bool startEventLoop = false;
do
{
d->m_pixmapRequestsMutex.lock();
startEventLoop = !d->m_executingPixmapRequests.isEmpty();
d->m_pixmapRequestsMutex.unlock();
if ( startEventLoop )
{
d->m_closingLoop = &loop;
loop.exec();
d->m_closingLoop = nullptr;
}
}
while ( startEventLoop );
if ( d->m_fontThread ) if ( d->m_fontThread )
{ {
@ -4356,6 +4361,8 @@ bool Document::swapBackingFile( const QString &newFileName, const QUrl &url )
// Save metadata about the file we're about to close // Save metadata about the file we're about to close
d->saveDocumentInfo(); d->saveDocumentInfo();
d->clearAndWaitForRequests();
qCDebug(OkularCoreDebug) << "Swapping backing file to" << newFileName; qCDebug(OkularCoreDebug) << "Swapping backing file to" << newFileName;
QVector< Page * > newPagesVector; QVector< Page * > newPagesVector;
Generator::SwapBackingFileResult result = genIt->generator->swapBackingFile( newFileName, newPagesVector ); Generator::SwapBackingFileResult result = genIt->generator->swapBackingFile( newFileName, newPagesVector );

View file

@ -202,6 +202,8 @@ class DocumentPrivate
// For sync files // For sync files
void loadSyncFile( const QString & filePath ); void loadSyncFile( const QString & filePath );
void clearAndWaitForRequests();
// member variables // member variables
Document *m_parent; Document *m_parent;
QPointer<QWidget> m_widget; QPointer<QWidget> m_widget;