Skip to content

Commit 7230475

Browse files
authored
Merge pull request #34 from CppCXY/master
修复线程安全问题
2 parents bb1fe5f + 4572c8d commit 7230475

File tree

4 files changed

+92
-74
lines changed

4 files changed

+92
-74
lines changed

emmy_debugger/src/emmy_debugger.cpp

Lines changed: 21 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void Debugger::Start()
5555
doStringList.clear();
5656
}
5757

58-
void Debugger::Attach(bool isMainThread)
58+
void Debugger::Attach()
5959
{
6060
if (!running)
6161
return;
@@ -83,25 +83,25 @@ void Debugger::Attach(bool isMainThread)
8383
lua_settop(L, t);
8484
});
8585
}
86-
87-
if (EmmyFacade::Get().GetWorkMode() == WorkMode::EmmyCore && mainL)
88-
{
89-
if (isMainThread)
90-
{
91-
auto states = FindAllCoroutine(mainL);
92-
93-
for (auto state : states)
94-
{
95-
lua_sethook(state, EmmyFacade::HookLua, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
96-
}
97-
98-
lua_sethook(mainL, EmmyFacade::HookLua, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
99-
}
100-
else
101-
{
102-
SetInitHook();
103-
}
104-
}
86+
//
87+
// if (EmmyFacade::Get().GetWorkMode() == WorkMode::EmmyCore && mainL)
88+
// {
89+
// if (isMainThread)
90+
// {
91+
// auto states = FindAllCoroutine(mainL);
92+
//
93+
// for (auto state : states)
94+
// {
95+
// lua_sethook(state, EmmyFacade::HookLua, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
96+
// }
97+
//
98+
// lua_sethook(mainL, EmmyFacade::HookLua, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
99+
// }
100+
// else
101+
// {
102+
// SetInitHook();
103+
// }
104+
// }
105105
}
106106

107107
void Debugger::Detach()
@@ -160,6 +160,7 @@ void Debugger::Hook(lua_Debug* ar, lua_State* L)
160160
}
161161
}
162162

163+
163164
void Debugger::Stop()
164165
{
165166
running = false;
@@ -589,15 +590,6 @@ void Debugger::UpdateHook(int mask, lua_State* L)
589590
lua_sethook(L, EmmyFacade::HookLua, mask, 0);
590591
}
591592

592-
void Debugger::SetInitHook()
593-
{
594-
lua_sethook(mainL, EmmyFacade::InitHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
595-
}
596-
597-
void Debugger::SetWaitConnectedHook(lua_State* L)
598-
{
599-
lua_sethook(L, WaitConnectedHook,LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
600-
}
601593

602594
// _G.emmy.fixPath = function(path) return (newPath) end
603595
int FixPath(lua_State* L)

emmy_debugger/src/emmy_facade.cpp

Lines changed: 58 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,18 @@ void EmmyFacade::HookLua(lua_State* L, lua_Debug* ar)
3737
EmmyFacade::Get().Hook(L, ar);
3838
}
3939

40-
void EmmyFacade::InitHook(lua_State* L, lua_Debug* ar)
40+
void EmmyFacade::ReadyLuaHook(lua_State* L, lua_Debug* ar)
4141
{
42-
auto mainL = GetMainState(L);
42+
{
43+
std::lock_guard<std::mutex> lock(EmmyFacade::Get().readyHookMtx);
44+
if (!EmmyFacade::Get().readyHook)
45+
{
46+
return;
47+
}
48+
EmmyFacade::Get().readyHook = false;
49+
}
4350

44-
auto states = FindAllCoroutine(mainL);
51+
auto states = FindAllCoroutine(L);
4552

4653
for (auto state : states)
4754
{
@@ -50,6 +57,12 @@ void EmmyFacade::InitHook(lua_State* L, lua_Debug* ar)
5057

5158
lua_sethook(L, HookLua, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
5259

60+
auto debugger = EmmyFacade::Get().GetDebugger(L);
61+
if (debugger)
62+
{
63+
debugger->Attach();
64+
}
65+
5366
EmmyFacade::Get().Hook(L, ar);
5467
}
5568

@@ -60,7 +73,8 @@ EmmyFacade::EmmyFacade()
6073
isWaitingForIDE(false),
6174
StartHook(nullptr),
6275
workMode(WorkMode::EmmyCore),
63-
emmyDebuggerManager(std::make_shared<EmmyDebuggerManager>())
76+
emmyDebuggerManager(std::make_shared<EmmyDebuggerManager>()),
77+
readyHook(false)
6478
{
6579
}
6680

@@ -103,11 +117,10 @@ bool EmmyFacade::TcpListen(lua_State* L, const std::string& host, int port, std:
103117
{
104118
Destroy();
105119

106-
// 仅仅luajit需要
107-
mainStates.insert(L);
108-
109120
emmyDebuggerManager->AddDebugger(L);
110121

122+
SetReadyHook(L);
123+
111124
const auto s = std::make_shared<SocketServerTransporter>();
112125
transporter = s;
113126
// s->SetHandler(shared_from_this());
@@ -134,11 +147,10 @@ bool EmmyFacade::TcpConnect(lua_State* L, const std::string& host, int port, std
134147
{
135148
Destroy();
136149

137-
// 仅仅luajit需要
138-
mainStates.insert(L);
139-
140150
emmyDebuggerManager->AddDebugger(L);
141151

152+
SetReadyHook(L);
153+
142154
const auto c = std::make_shared<SocketClientTransporter>();
143155
transporter = c;
144156
// c->SetHandler(shared_from_this());
@@ -160,11 +172,10 @@ bool EmmyFacade::PipeListen(lua_State* L, const std::string& name, std::string&
160172
{
161173
Destroy();
162174

163-
// 仅仅luajit需要
164-
mainStates.insert(L);
165-
166175
emmyDebuggerManager->AddDebugger(L);
167176

177+
SetReadyHook(L);
178+
168179
const auto p = std::make_shared<PipelineServerTransporter>();
169180
transporter = p;
170181
// p->SetHandler(shared_from_this());
@@ -176,11 +187,10 @@ bool EmmyFacade::PipeConnect(lua_State* L, const std::string& name, std::string&
176187
{
177188
Destroy();
178189

179-
// 仅仅luajit需要
180-
mainStates.insert(L);
181-
182190
emmyDebuggerManager->AddDebugger(L);
183191

192+
SetReadyHook(L);
193+
184194
const auto p = std::make_shared<PipelineClientTransporter>();
185195
transporter = p;
186196
// p->SetHandler(shared_from_this());
@@ -318,20 +328,13 @@ void EmmyFacade::OnInitReq(const rapidjson::Document& document)
318328
emmyDebuggerManager->extNames = extNames;
319329
}
320330

321-
emmyDebuggerManager->SetRunning(true);
322-
323-
//TODO 这里有个线程安全问题,消息线程和lua 执行线程不是相同线程,但是没有一个锁能让我做同步
331+
// 这里有个线程安全问题,消息线程和lua 执行线程不是相同线程,但是没有一个锁能让我做同步
324332
// 所以我不能在这里访问lua state 指针的内部结构
325333
//
326-
// 只能在消息线程设置hook
327-
// 但是存在一个问题只能给主lua_state 设置hook,如果此后进程一直在协程中执行则无法触发该hook
328-
// Attach函数内部设置了hook,存在一个线程问题,可能引发崩溃
329334
// 方案:提前为主state 设置hook 利用hook 实现同步
330-
auto debuggers = emmyDebuggerManager->GetDebuggers();
331-
for (auto debugger : debuggers)
332-
{
333-
debugger->Attach(false);
334-
}
335+
336+
// fix 以上安全问题
337+
StartDebug();
335338
}
336339

337340
void EmmyFacade::OnReadyReq(const rapidjson::Document& document)
@@ -598,6 +601,20 @@ void EmmyFacade::Hook(lua_State* L, lua_Debug* ar)
598601
{
599602
if (!debugger->IsRunning())
600603
{
604+
if (EmmyFacade::Get().GetWorkMode() == WorkMode::EmmyCore)
605+
{
606+
if (luaVersion != LuaVersion::LUA_JIT)
607+
{
608+
if (debugger->IsMainCoroutine(L))
609+
{
610+
SetReadyHook(L);
611+
}
612+
}
613+
else
614+
{
615+
SetReadyHook(L);
616+
}
617+
}
601618
return;
602619
}
603620

@@ -609,7 +626,8 @@ void EmmyFacade::Hook(lua_State* L, lua_Debug* ar)
609626
{
610627
debugger = emmyDebuggerManager->AddDebugger(L);
611628
install_emmy_core(L);
612-
if (emmyDebuggerManager->IsRunning()) {
629+
if (emmyDebuggerManager->IsRunning())
630+
{
613631
debugger->Start();
614632
debugger->Attach();
615633
}
@@ -666,6 +684,18 @@ std::shared_ptr<Debugger> EmmyFacade::GetDebugger(lua_State* L)
666684
return emmyDebuggerManager->GetDebugger(L);
667685
}
668686

687+
void EmmyFacade::SetReadyHook(lua_State* L)
688+
{
689+
lua_sethook(L, ReadyLuaHook, LUA_MASKCALL | LUA_MASKLINE | LUA_MASKRET, 0);
690+
}
691+
692+
void EmmyFacade::StartDebug()
693+
{
694+
emmyDebuggerManager->SetRunning(true);
695+
std::lock_guard<std::mutex> lock(EmmyFacade::Get().readyHookMtx);
696+
EmmyFacade::Get().readyHook = true;
697+
}
698+
669699
void EmmyFacade::StartupHookMode(int port)
670700
{
671701
Destroy();

include/emmy_debugger/emmy_debugger.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ class Debugger : public std::enable_shared_from_this<Debugger>
3838
~Debugger();
3939

4040
void Start();
41-
/*
42-
* @param isMainThread 代表是否是在主线程执行
43-
*/
44-
void Attach(bool isMainThread = true);
41+
42+
void Attach();
4543
/*
4644
* 主lua state 销毁时,所做工作
4745
*/
@@ -52,6 +50,7 @@ class Debugger : public std::enable_shared_from_this<Debugger>
5250
* hook时调用
5351
*/
5452
void Hook(lua_Debug* ar, lua_State* L);
53+
5554
/*
5655
* 停止调试时调用
5756
*/
@@ -82,16 +81,6 @@ class Debugger : public std::enable_shared_from_this<Debugger>
8281
* 更新hook
8382
*/
8483
void UpdateHook(int mask, lua_State* L);
85-
/*
86-
* 设置初始化hook
87-
*/
88-
void SetInitHook();
89-
90-
/*
91-
* 该思路暂时未启用
92-
* 设置等待连接的hook
93-
*/
94-
void SetWaitConnectedHook(lua_State* L);
9584

9685
/*
9786
* 设置当前状态机,他的锁由doAction负责
@@ -117,8 +106,6 @@ class Debugger : public std::enable_shared_from_this<Debugger>
117106
// bool HasCacheValue(int valueIndex) const;
118107
void ClearCache() const;
119108

120-
// std::mutex waitConnectedMtx;
121-
122109
lua_State* currentL;
123110
lua_State* mainL;
124111

include/emmy_debugger/emmy_facade.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class EmmyFacade
4343

4444
static void HookLua(lua_State* L, lua_Debug* ar);
4545

46-
static void InitHook(lua_State* L, lua_Debug* ar);
46+
static void ReadyLuaHook(lua_State* L, lua_Debug* ar);
4747

4848
EmmyFacade();
4949
~EmmyFacade();
@@ -75,6 +75,10 @@ class EmmyFacade
7575
void RemoveVariableRef(Variable* variable);
7676
std::shared_ptr<Debugger> GetDebugger(lua_State* L);
7777

78+
void SetReadyHook(lua_State* L);
79+
80+
void StartDebug();
81+
7882
// for hook
7983
void StartupHookMode(int port);
8084
void Attach(lua_State* L);
@@ -107,6 +111,11 @@ class EmmyFacade
107111

108112
// 表示使用了tcplisten tcpConnect 的states
109113
std::set<lua_State*> mainStates;
114+
115+
std::mutex readyHookMtx;
116+
bool readyHook;
110117
};
111118

112119

120+
121+

0 commit comments

Comments
 (0)