Skip to content

Commit 176b5d0

Browse files
committed
Improve error handling in SwiftUserExpression.
Previously this ``` $ swiftc test.swift -g -o test $ lldb -o 'b main' -o 'b test' -o r -o 'e -i0 -- test()' ./test (lldb) ^D ``` resulted in ``` Can't execute a swift expression without a runtime UNREACHABLE executed at llvm-project/lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp:90! ``` after this patch it's ``` (lldb) ^D error: Could not finish swift expression because the process is being torn down ``` Unfortunately catching this error in a test case is tricky.
1 parent 4b0b1f9 commit 176b5d0

File tree

5 files changed

+55
-10
lines changed

5 files changed

+55
-10
lines changed

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.cpp

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#endif
2525

2626
#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h"
27+
#include "lldb/Core/Debugger.h"
2728
#include "lldb/Core/Module.h"
2829
#include "lldb/Expression/DiagnosticManager.h"
2930
#include "lldb/Expression/ExpressionParser.h"
@@ -65,31 +66,49 @@ SwiftUserExpression::SwiftUserExpression(
6566
m_result_delegate(exe_scope.CalculateTarget(), *this, false),
6667
m_error_delegate(exe_scope.CalculateTarget(), *this, true),
6768
m_persistent_variable_delegate(*this) {
69+
if (auto target = exe_scope.CalculateTarget())
70+
m_debugger_id = target->GetDebugger().GetID();
6871
m_runs_in_playground_or_repl =
6972
options.GetREPLEnabled() || options.GetPlaygroundTransformEnabled();
7073
}
7174

7275
SwiftUserExpression::~SwiftUserExpression() {}
7376

7477
void SwiftUserExpression::WillStartExecuting() {
75-
if (auto process = m_jit_process_wp.lock()) {
78+
if (auto process = m_jit_process_wp.lock())
7679
if (auto *swift_runtime = SwiftLanguageRuntime::Get(process))
7780
swift_runtime->WillStartExecutingUserExpression(
7881
m_runs_in_playground_or_repl);
7982
else
80-
llvm_unreachable("Can't execute a swift expression without a runtime");
81-
} else
82-
llvm_unreachable("Can't execute an expression without a process");
83+
Debugger::ReportError(
84+
"Can't execute a swift expression without a runtime",
85+
m_debugger_id);
86+
else
87+
Debugger::ReportError("Can't execute an expression without a process",
88+
m_debugger_id);
8389
}
8490

8591
void SwiftUserExpression::DidFinishExecuting() {
86-
if (auto process = m_jit_process_wp.lock()) {
87-
if (auto *swift_runtime = SwiftLanguageRuntime::Get(process))
88-
swift_runtime->DidFinishExecutingUserExpression(
89-
m_runs_in_playground_or_repl);
90-
else
91-
llvm_unreachable("Can't execute a swift expression without a runtime");
92+
auto process = m_jit_process_wp.lock();
93+
if (!process) {
94+
Debugger::ReportError("Could not finish a expression without a process",
95+
m_debugger_id);
96+
return;
97+
}
98+
if (!process->IsValid()) {
99+
// This will cause SwiftLanguageRuntime::Get(process) tp fail.
100+
Debugger::ReportError("Could not finish swift expression because the "
101+
"process is being torn down",
102+
m_debugger_id);
103+
return;
104+
}
105+
auto *swift_runtime = SwiftLanguageRuntime::Get(process);
106+
if (!swift_runtime) {
107+
Debugger::ReportError("Could not finish swift expression without a runtime",
108+
m_debugger_id);
109+
return;
92110
}
111+
swift_runtime->DidFinishExecutingUserExpression(m_runs_in_playground_or_repl);
93112
}
94113

95114
/// Determine whether we have a Swift language symbol context. This handles

lldb/source/Plugins/ExpressionParser/Swift/SwiftUserExpression.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ class SwiftUserExpression : public LLVMUserExpression {
194194
PersistentVariableDelegate m_persistent_variable_delegate;
195195
std::unique_ptr<SwiftExpressionParser> m_parser;
196196
std::optional<SwiftLanguageRuntime::GenericSignature> m_generic_signature;
197+
std::optional<lldb::user_id_t> m_debugger_id;
197198
Status m_err;
198199
bool m_runs_in_playground_or_repl;
199200
bool m_needs_object_ptr = false;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
SWIFT_SOURCES := main.swift
2+
include Makefile.rules
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import unittest2
6+
7+
class TestSwiftNoRuntime(TestBase):
8+
NO_DEBUG_INFO_TESTCASE = True
9+
10+
@swiftTest
11+
def test(self):
12+
"""Test running a Swift expression in a C program"""
13+
self.build()
14+
self.expect("b test")
15+
_, process, _, _ = lldbutil.run_to_name_breakpoint(self, "main")
16+
options = lldb.SBExpressionOptions()
17+
options.SetIgnoreBreakpoints(False);
18+
value = self.frame().EvaluateExpression("test()", options)
19+
self.assertIn("breakpoint", str(value.GetError()))
20+
process.Kill()
21+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
func test() {}
2+

0 commit comments

Comments
 (0)