Skip to content

Commit b5b99d5

Browse files
committed
Fix DataReaderThead termination deadlook (#1441)
If realRun is not reaching attach(), the schedule on main thread do nothing. So we need to introduce a separate bit to avoid such race.
1 parent d45b8d1 commit b5b99d5

File tree

2 files changed

+22
-1
lines changed

2 files changed

+22
-1
lines changed

src/modules/clipboard/waylandclipboard.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <unistd.h>
99
#include <cstdint>
1010
#include <memory>
11+
#include <mutex>
1112
#include <string>
1213
#include <string_view>
1314
#include <unordered_set>
@@ -60,7 +61,14 @@ void DataReaderThread::removeTask(uint64_t token) {
6061
void DataReaderThread::realRun() {
6162
EventLoop loop;
6263
dispatcherToWorker_.attach(&loop);
63-
loop.exec();
64+
bool terminate = false;
65+
{
66+
std::lock_guard<std::mutex> lock(mutex_);
67+
terminate = terminate_;
68+
}
69+
if (!terminate) {
70+
loop.exec();
71+
}
6472
dispatcherToWorker_.detach();
6573
FCITX_DEBUG() << "Ending DataReaderThread";
6674
tasks_.clear();

src/modules/clipboard/waylandclipboard.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <functional>
1212
#include <list>
1313
#include <memory>
14+
#include <mutex>
1415
#include <string>
1516
#include <thread>
1617
#include <unordered_map>
@@ -75,6 +76,13 @@ class DataReaderThread {
7576

7677
~DataReaderThread() {
7778
if (thread_ && thread_->joinable()) {
79+
{
80+
std::lock_guard<std::mutex> lock(mutex_);
81+
terminate_ = true;
82+
}
83+
// If dispatcher is not attched, the schedule will do nothing.
84+
// But after attach, reader thread will check terminate_
85+
// So it won't stuck forever.
7886
dispatcherToWorker_.schedule([this]() {
7987
if (auto *loop = dispatcherToWorker_.eventLoop()) {
8088
loop->exit();
@@ -109,6 +117,11 @@ class DataReaderThread {
109117
std::unique_ptr<std::thread> thread_;
110118
uint64_t nextId_ = 1;
111119

120+
// Accessed by both thread
121+
std::mutex mutex_;
122+
bool terminate_ = false;
123+
// End Accessed by both thread
124+
112125
// Value only read/write by the reader thread.
113126
EventDispatcher dispatcherToWorker_;
114127
std::unordered_map<uint64_t, DataOfferTask> tasks_;

0 commit comments

Comments
 (0)