* @brief Synchronously closes the worker DB and joins the worker thread. If the join times * out the worker and thread are leaked on purpose: deleting objects a live thread is * still executing trades a one-time leak at shutdown for a use-after-free. */
| 176 | * still executing trades a one-time leak at shutdown for a use-after-free. |
| 177 | */ |
| 178 | void Sessions::DatabaseManager::shutdown() |
| 179 | { |
| 180 | if (!m_thread) |
| 181 | return; |
| 182 | |
| 183 | if (m_worker) |
| 184 | m_worker->requestCancel(); |
| 185 | |
| 186 | bool joined = true; |
| 187 | if (QCoreApplication::instance() && m_thread->isRunning() && m_worker) { |
| 188 | QMetaObject::invokeMethod(m_worker, "closeDatabase", Qt::BlockingQueuedConnection); |
| 189 | m_thread->quit(); |
| 190 | joined = m_thread->wait(5000); |
| 191 | } |
| 192 | |
| 193 | if (!joined) { |
| 194 | qWarning() << "[Sessions] Database worker did not stop within 5 s; leaking the worker " |
| 195 | "thread to avoid tearing down objects it still uses"; |
| 196 | m_worker = nullptr; |
| 197 | m_thread = nullptr; |
| 198 | return; |
| 199 | } |
| 200 | |
| 201 | delete m_worker; |
| 202 | m_worker = nullptr; |
| 203 | |
| 204 | delete m_thread; |
| 205 | m_thread = nullptr; |
| 206 | } |
| 207 | |
| 208 | //-------------------------------------------------------------------------------------------------- |
| 209 | // External connections |
nothing calls this directly
no test coverage detected