Commit 7a90acf8699f11cd1c4844c64e710e7522f20dd6
1 parent
477dd009
Add finish timeout on threads on exit
Showing
2 changed files
with
27 additions
and
2 deletions
mainapp.cpp
| ... | ... | @@ -170,6 +170,8 @@ void do_thread_work(ThreadData *threadData) |
| 170 | 170 | { |
| 171 | 171 | logger->logf(LOG_ERR, "Error cleaning auth back-end: %s", ex.what()); |
| 172 | 172 | } |
| 173 | + | |
| 174 | + threadData->finished = true; | |
| 173 | 175 | } |
| 174 | 176 | |
| 175 | 177 | |
| ... | ... | @@ -697,14 +699,36 @@ void MainApp::start() |
| 697 | 699 | |
| 698 | 700 | oneInstanceLock.unlock(); |
| 699 | 701 | |
| 702 | + logger->logf(LOG_DEBUG, "Signaling threads to finish."); | |
| 700 | 703 | for(std::shared_ptr<ThreadData> &thread : threads) |
| 701 | 704 | { |
| 702 | 705 | thread->queueQuit(); |
| 703 | 706 | } |
| 704 | 707 | |
| 705 | - for(std::shared_ptr<ThreadData> &thread : threads) | |
| 708 | + logger->logf(LOG_DEBUG, "Waiting for threads to finish."); | |
| 709 | + int count = 0; | |
| 710 | + bool waitTimeExpired = false; | |
| 711 | + while(std::any_of(threads.begin(), threads.end(), [](std::shared_ptr<ThreadData> t){ return !t->finished; })) | |
| 712 | + { | |
| 713 | + if (count++ >= 5000) | |
| 714 | + { | |
| 715 | + waitTimeExpired = true; | |
| 716 | + break; | |
| 717 | + } | |
| 718 | + usleep(1000); | |
| 719 | + } | |
| 720 | + | |
| 721 | + if (waitTimeExpired) | |
| 722 | + { | |
| 723 | + logger->logf(LOG_WARNING, "(Some) threads failed to terminate. Program will exit uncleanly. If you're using a plugin, it may not be thread-safe."); | |
| 724 | + } | |
| 725 | + else | |
| 706 | 726 | { |
| 707 | - thread->waitForQuit(); | |
| 727 | + for(std::shared_ptr<ThreadData> &thread : threads) | |
| 728 | + { | |
| 729 | + logger->logf(LOG_DEBUG, "Waiting for thread %d to join.", thread->threadnr); | |
| 730 | + thread->waitForQuit(); | |
| 731 | + } | |
| 708 | 732 | } |
| 709 | 733 | |
| 710 | 734 | saveState(); | ... | ... |
threaddata.h