diff --git a/src/core/scheduler.cpp b/src/core/scheduler.cpp --- a/src/core/scheduler.cpp +++ b/src/core/scheduler.cpp @@ -129,6 +129,11 @@ return false; } +void SlaveKeeper::clear() +{ + m_idleSlaves.clear(); +} + QList SlaveKeeper::allSlaves() const { return m_idleSlaves.values(); @@ -404,7 +409,11 @@ ProtoQueue::~ProtoQueue() { - Q_FOREACH (Slave *slave, allSlaves()) { + // Gather list of all slaves first + const QList slaves = allSlaves(); + // Clear the idle slaves in the keeper to avoid dangling pointers + m_slaveKeeper.clear(); + for (Slave *slave : slaves) { // kill the slave process, then remove the interface in our process slave->kill(); slave->deref(); @@ -1123,7 +1132,9 @@ m_slaveOnHold = nullptr; m_urlOnHold.clear(); } - slave->deref(); // Delete slave + // can't use slave->deref() here because we need to use deleteLater + slave->aboutToDelete(); + slave->deleteLater(); } void SchedulerPrivate::putSlaveOnHold(KIO::SimpleJob *job, const QUrl &url) diff --git a/src/core/scheduler_p.h b/src/core/scheduler_p.h --- a/src/core/scheduler_p.h +++ b/src/core/scheduler_p.h @@ -25,6 +25,7 @@ namespace KIO { +// The slave keeper manages the list of idle slaves that can be reused class SlaveKeeper : public QObject { Q_OBJECT @@ -37,6 +38,8 @@ KIO::Slave *takeSlaveForJob(KIO::SimpleJob *job); // remove slave from keeper bool removeSlave(KIO::Slave *slave); + // remove all slaves from keeper + void clear(); QList allSlaves() const; private: diff --git a/src/core/slave.h b/src/core/slave.h --- a/src/core/slave.h +++ b/src/core/slave.h @@ -229,6 +229,7 @@ void ref(); void deref(); + void aboutToDelete(); public Q_SLOTS: void accept(); diff --git a/src/core/slave.cpp b/src/core/slave.cpp --- a/src/core/slave.cpp +++ b/src/core/slave.cpp @@ -298,12 +298,18 @@ Q_D(Slave); d->m_refCount--; if (!d->m_refCount) { - d->connection->disconnect(this); - this->disconnect(); - deleteLater(); + aboutToDelete(); + delete this; // yes it reads funny, but it's too late for a deleteLater() here, no event loop anymore } } +void Slave::aboutToDelete() +{ + Q_D(Slave); + d->connection->disconnect(this); + this->disconnect(); +} + int Slave::idleTime() { Q_D(Slave);