Skip to content

Commit 883348e

Browse files
xusheng6claude
andauthored
Hold a strong reference to DebuggerController in detached worker threads (#1086)
The 17 `Launch`/`Attach`/`Connect`/`Go`/`Step*`/`RunTo*`/`Restart`/`Detach`/ `Quit`/`Pause` methods each spawn a detached `std::thread` that runs the corresponding `*AndWait` work, capturing `this` by reference. Nothing keeps the controller alive for the duration of the detached call, so if the controller's refcount drops to zero before the worker exits (e.g. the user closes the tab), the worker dereferences a dangling pointer. Capture a `DbgRef<DebuggerController>` by value into each lambda so the controller stays alive until the worker thread finishes. Fixes #1083. Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
1 parent e2b7467 commit 883348e

1 file changed

Lines changed: 34 additions & 17 deletions

File tree

core/debuggercontroller.cpp

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,8 @@ bool DebuggerController::Launch()
290290
if (!CanStartDebgging())
291291
return false;
292292

293-
std::thread([&]() { LaunchAndWait(); }).detach();
293+
DbgRef<DebuggerController> self = this;
294+
std::thread([self]() { self->LaunchAndWait(); }).detach();
294295
return true;
295296
}
296297

@@ -353,7 +354,8 @@ bool DebuggerController::Attach()
353354
if (!CanStartDebgging())
354355
return false;
355356

356-
std::thread([&]() { AttachAndWait(); }).detach();
357+
DbgRef<DebuggerController> self = this;
358+
std::thread([self]() { self->AttachAndWait(); }).detach();
357359
return true;
358360
}
359361

@@ -404,7 +406,8 @@ bool DebuggerController::Connect()
404406
if (!CanStartDebgging())
405407
return false;
406408

407-
std::thread([&]() { ConnectAndWait(); }).detach();
409+
DbgRef<DebuggerController> self = this;
410+
std::thread([self]() { self->ConnectAndWait(); }).detach();
408411
return true;
409412
}
410413

@@ -543,7 +546,8 @@ bool DebuggerController::Go()
543546
if (!CanResumeTarget())
544547
return false;
545548

546-
std::thread([&]() { GoAndWait(); }).detach();
549+
DbgRef<DebuggerController> self = this;
550+
std::thread([self]() { self->GoAndWait(); }).detach();
547551

548552
return true;
549553
}
@@ -554,7 +558,8 @@ bool DebuggerController::GoReverse()
554558
if (!CanResumeTarget())
555559
return false;
556560

557-
std::thread([&]() { GoReverseAndWait(); }).detach();
561+
DbgRef<DebuggerController> self = this;
562+
std::thread([self]() { self->GoReverseAndWait(); }).detach();
558563

559564
return true;
560565
}
@@ -817,7 +822,8 @@ bool DebuggerController::StepInto(BNFunctionGraphType il)
817822
if (!CanResumeTarget())
818823
return false;
819824

820-
std::thread([&, il]() { StepIntoAndWait(il); }).detach();
825+
DbgRef<DebuggerController> self = this;
826+
std::thread([self, il]() { self->StepIntoAndWait(il); }).detach();
821827

822828
return true;
823829
}
@@ -827,7 +833,8 @@ bool DebuggerController::StepIntoReverse(BNFunctionGraphType il)
827833
if (!CanResumeTarget())
828834
return false;
829835

830-
std::thread([&, il]() { StepIntoReverseAndWait(il); }).detach();
836+
DbgRef<DebuggerController> self = this;
837+
std::thread([self, il]() { self->StepIntoReverseAndWait(il); }).detach();
831838

832839
return true;
833840
}
@@ -1078,7 +1085,8 @@ bool DebuggerController::StepOver(BNFunctionGraphType il)
10781085
if (!CanResumeTarget())
10791086
return false;
10801087

1081-
std::thread([&, il]() { StepOverAndWait(il); }).detach();
1088+
DbgRef<DebuggerController> self = this;
1089+
std::thread([self, il]() { self->StepOverAndWait(il); }).detach();
10821090

10831091
return true;
10841092
}
@@ -1089,7 +1097,8 @@ bool DebuggerController::StepOverReverse(BNFunctionGraphType il)
10891097
if (!CanResumeTarget())
10901098
return false;
10911099

1092-
std::thread([&, il]() { StepOverReverseAndWait(il); }).detach();
1100+
DbgRef<DebuggerController> self = this;
1101+
std::thread([self, il]() { self->StepOverReverseAndWait(il); }).detach();
10931102

10941103
return true;
10951104
}
@@ -1184,7 +1193,8 @@ bool DebuggerController::StepReturn()
11841193
if (!CanResumeTarget())
11851194
return false;
11861195

1187-
std::thread([&]() { StepReturnAndWait(); }).detach();
1196+
DbgRef<DebuggerController> self = this;
1197+
std::thread([self]() { self->StepReturnAndWait(); }).detach();
11881198

11891199
return true;
11901200
}
@@ -1195,7 +1205,8 @@ bool DebuggerController::StepReturnReverse()
11951205
if (!CanResumeTarget())
11961206
return false;
11971207

1198-
std::thread([&]() { StepReturnReverseAndWait(); }).detach();
1208+
DbgRef<DebuggerController> self = this;
1209+
std::thread([self]() { self->StepReturnReverseAndWait(); }).detach();
11991210

12001211
return true;
12011212
}
@@ -1295,7 +1306,8 @@ bool DebuggerController::RunTo(const std::vector<uint64_t>& remoteAddresses)
12951306
if (!CanResumeTarget())
12961307
return false;
12971308

1298-
std::thread([&, remoteAddresses]() { RunToAndWait(remoteAddresses); }).detach();
1309+
DbgRef<DebuggerController> self = this;
1310+
std::thread([self, remoteAddresses]() { self->RunToAndWait(remoteAddresses); }).detach();
12991311

13001312
return true;
13011313
}
@@ -1307,7 +1319,8 @@ bool DebuggerController::RunToReverse(const std::vector<uint64_t>& remoteAddress
13071319
if (!CanResumeTarget())
13081320
return false;
13091321

1310-
std::thread([&, remoteAddresses]() { RunToReverseAndWait(remoteAddresses); }).detach();
1322+
DbgRef<DebuggerController> self = this;
1323+
std::thread([self, remoteAddresses]() { self->RunToReverseAndWait(remoteAddresses); }).detach();
13111324

13121325
return true;
13131326
}
@@ -1457,7 +1470,8 @@ bool DebuggerController::Restart()
14571470
if (!m_state->IsConnected())
14581471
return false;
14591472

1460-
std::thread([&]() { RestartAndWait(); }).detach();
1473+
DbgRef<DebuggerController> self = this;
1474+
std::thread([self]() { self->RestartAndWait(); }).detach();
14611475
return true;
14621476
}
14631477

@@ -1517,7 +1531,8 @@ void DebuggerController::Detach()
15171531
if (!m_state->IsConnected())
15181532
return;
15191533

1520-
std::thread([&]() { DetachAndWait(); }).detach();
1534+
DbgRef<DebuggerController> self = this;
1535+
std::thread([self]() { self->DetachAndWait(); }).detach();
15211536
}
15221537

15231538

@@ -1550,7 +1565,8 @@ void DebuggerController::Quit()
15501565
if (!m_state->IsConnected())
15511566
return;
15521567

1553-
std::thread([&]() { QuitAndWait(); }).detach();
1568+
DbgRef<DebuggerController> self = this;
1569+
std::thread([self]() { self->QuitAndWait(); }).detach();
15541570
}
15551571

15561572

@@ -1589,7 +1605,8 @@ bool DebuggerController::Pause()
15891605
if (!m_state->IsConnected())
15901606
return false;
15911607

1592-
std::thread([&]() { PauseAndWait(); }).detach();
1608+
DbgRef<DebuggerController> self = this;
1609+
std::thread([self]() { self->PauseAndWait(); }).detach();
15931610

15941611
return true;
15951612
}

0 commit comments

Comments
 (0)