Commit 1050ceb3 authored by Raphael Kubo da Costa's avatar Raphael Kubo da Costa
Browse files

Make ark stop crashing here on every startup due to threading problems.

Now only the interface object is moved to the worker thread, and then
returned back to the original thread.
TODO: ThreadExecution knows too much about the internals of Job, so a
refactoring is welcome.

svn path=/trunk/KDE/kdeutils/ark/; revision=956398
parent 60a37619
......@@ -68,16 +68,15 @@ namespace Kerfuffle
#ifdef KERFUFFLE_NOJOBTHREADING
QTimer::singleShot(0, this, SLOT(doWork()));
#else
m_workerThread = new ThreadExecution(this);
//we want the event handling to happen in the work thread to avoid
//unsafe data access due to events while work is being done
kDebug() << "Moving from " << QObject::thread() << " to " << m_workerThread;
m_previousInterfaceParent = m_interface->parent();
m_interface->setParent(NULL);
m_interface->moveToThread(m_workerThread);
moveToThread(m_workerThread);
m_workerThread = new ThreadExecution(this);
connect(m_workerThread, SIGNAL(finished()), this, SLOT(returnToMainThread()));
connect(m_workerThread, SIGNAL(terminated()), this, SLOT(returnToMainThread()));
m_workerThread->start();
#endif
}
......@@ -116,15 +115,18 @@ namespace Kerfuffle
m_interface->removeObserver( this );
setError(!result);
}
void Job::returnToMainThread()
{
kDebug();
#ifndef KERFUFFLE_NOJOBTHREADING
kDebug() << "Moving from " << QObject::thread()<< " to " << QApplication::instance()->thread();
m_interface->moveToThread(QApplication::instance()->thread());
Q_ASSERT(m_interface->thread() != m_workerThread);
Q_ASSERT(m_previousInterfaceParent);
m_interface->setParent(m_previousInterfaceParent);
moveToThread(QApplication::instance()->thread());
#endif
emitResult();
}
void Job::onUserQuery(Query *query)
......@@ -157,6 +159,7 @@ namespace Kerfuffle
m_interface->registerObserver( this );
bool ret = m_interface->list();
emitResult();
if (!m_interface->waitForFinishedSignal()) m_interface->finished(ret);
}
......@@ -220,6 +223,8 @@ namespace Kerfuffle
;
bool ret = m_interface->copyFiles( m_files, m_destinationDir, m_options );
emitResult();
if (!m_interface->waitForFinishedSignal()) m_interface->finished(ret);
}
......@@ -247,6 +252,7 @@ namespace Kerfuffle
m_writeInterface->registerObserver( this );
bool ret = m_writeInterface->addFiles( m_files, m_options );
emitResult();
if (!m_interface->waitForFinishedSignal()) m_interface->finished(ret);
}
......
......@@ -62,6 +62,9 @@ namespace Kerfuffle
public slots:
virtual void doWork() = 0;
private slots:
void returnToMainThread();
signals:
void userQuery( Query* );
void newEntry( const ArchiveEntry & );
......@@ -74,10 +77,11 @@ namespace Kerfuffle
ReadOnlyArchiveInterface* m_interface;
QObject *m_previousInterfaceParent;
ThreadExecution *m_workerThread;
virtual bool doKill();
private:
ThreadExecution *m_workerThread;
};
class KERFUFFLE_EXPORT ListJob: public Job
......
......@@ -32,7 +32,12 @@ namespace Kerfuffle
{
ThreadExecution::ThreadExecution(Kerfuffle::Job *job)
: m_job(job)
, m_interface(job->interface())
{
m_interface->setParent(NULL);
m_interface->moveToThread(this);
moveToThread(this);
}
void ThreadExecution::run()
......@@ -42,14 +47,19 @@ namespace Kerfuffle
QTimer::singleShot(0, m_job, SLOT(doWork()));
//and when finished, quit the event loop
connect(m_job, SIGNAL(result(KJob*)),
this, SLOT(quit()));
connect(m_job, SIGNAL(result(KJob*)), this, SLOT(slotJobFinished()));
connect(m_job, SIGNAL(result(KJob*)), this, SLOT(quit()));
//start the event loop
exec();
kDebug(1601) << "Finished exec";
}
void ThreadExecution::slotJobFinished()
{
m_interface->moveToThread(QApplication::instance()->thread());
}
}
#include "threading.moc"
......@@ -43,6 +43,10 @@ namespace Kerfuffle
private:
Kerfuffle::Job *m_job;
QObject *m_interface;
private slots:
void slotJobFinished();
};
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment