pub struct DebugSession { /* private fields */ }Expand description
A debug session attached to a single Lua instance.
Create with DebugSession::new, which also returns a
DebugController for the frontend.
§Lifecycle
new() → Idle → attach() → Running ⇄ Paused → Terminatedattach is a one-shot operation (per DAP
semantics). Calling it on a non-Idle session returns an error.
To re-attach, create a new DebugSession.
Implementations§
Source§impl DebugSession
impl DebugSession
Sourcepub fn new() -> (Self, DebugController)
pub fn new() -> (Self, DebugController)
Create a new debug session and its associated controller.
The session is in Idle state until attach is
called.
Examples found in repository?
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 let lua = Lua::new();
12
13 // Create debug session + controller.
14 let (session, controller) = DebugSession::new();
15 session.attach(&lua)?;
16
17 // Set a breakpoint on line 4.
18 let bp_id = controller.set_breakpoint("@example.lua", 4, None)?;
19 println!("Breakpoint {bp_id} set at @example.lua:4");
20
21 // Run Lua code on a separate thread.
22 // mlua 0.11's LuaError is not Send, so convert to a string error
23 // for cross-thread transport.
24 let handle = std::thread::spawn(move || -> Result<i64, String> {
25 lua.load(
26 r#"
27local a = 10
28local b = 20
29local c = 30
30local result = a + b + c
31return result
32"#,
33 )
34 .set_name("@example.lua")
35 .eval::<i64>()
36 .map_err(|e| e.to_string())
37 });
38
39 // Wait for the breakpoint hit.
40 match controller.wait_event()? {
41 DebugEvent::Paused { reason, stack } => {
42 println!("VM paused: {reason:?}");
43 for frame in &stack {
44 let line_str = frame
45 .line
46 .map_or_else(|| "?".to_string(), |l| l.to_string());
47 println!(
48 " frame {}: {} ({}:{})",
49 frame.id, frame.name, frame.source, line_str
50 );
51 }
52
53 // Inspect locals.
54 match controller.get_locals(0) {
55 Ok(locals) => {
56 println!("Locals:");
57 for var in &locals {
58 println!(" {} = {} ({})", var.name, var.value, var.type_name);
59 }
60 }
61 Err(e) => println!("Failed to get locals: {e}"),
62 }
63
64 // Evaluate an expression.
65 match controller.evaluate("a + b", None) {
66 Ok(result) => println!("Eval 'a + b' = {result}"),
67 Err(e) => println!("Eval failed: {e}"),
68 }
69 }
70 other => println!("Unexpected event: {other:?}"),
71 }
72
73 // Resume.
74 controller.continue_execution()?;
75
76 // Wait for completion.
77 let result = handle.join().unwrap()?;
78 println!("Lua returned: {result}");
79
80 Ok(())
81}Sourcepub fn attach(&self, lua: &Lua) -> LuaResult<()>
pub fn attach(&self, lua: &Lua) -> LuaResult<()>
Install the debug hook on the given Lua instance.
After this call, breakpoints and stepping become active.
§Errors
Returns an error if the session is not in SessionState::Idle
(e.g. already attached or terminated). Per DAP semantics,
attach/launch is a one-shot operation per session.
Examples found in repository?
10fn main() -> Result<(), Box<dyn std::error::Error>> {
11 let lua = Lua::new();
12
13 // Create debug session + controller.
14 let (session, controller) = DebugSession::new();
15 session.attach(&lua)?;
16
17 // Set a breakpoint on line 4.
18 let bp_id = controller.set_breakpoint("@example.lua", 4, None)?;
19 println!("Breakpoint {bp_id} set at @example.lua:4");
20
21 // Run Lua code on a separate thread.
22 // mlua 0.11's LuaError is not Send, so convert to a string error
23 // for cross-thread transport.
24 let handle = std::thread::spawn(move || -> Result<i64, String> {
25 lua.load(
26 r#"
27local a = 10
28local b = 20
29local c = 30
30local result = a + b + c
31return result
32"#,
33 )
34 .set_name("@example.lua")
35 .eval::<i64>()
36 .map_err(|e| e.to_string())
37 });
38
39 // Wait for the breakpoint hit.
40 match controller.wait_event()? {
41 DebugEvent::Paused { reason, stack } => {
42 println!("VM paused: {reason:?}");
43 for frame in &stack {
44 let line_str = frame
45 .line
46 .map_or_else(|| "?".to_string(), |l| l.to_string());
47 println!(
48 " frame {}: {} ({}:{})",
49 frame.id, frame.name, frame.source, line_str
50 );
51 }
52
53 // Inspect locals.
54 match controller.get_locals(0) {
55 Ok(locals) => {
56 println!("Locals:");
57 for var in &locals {
58 println!(" {} = {} ({})", var.name, var.value, var.type_name);
59 }
60 }
61 Err(e) => println!("Failed to get locals: {e}"),
62 }
63
64 // Evaluate an expression.
65 match controller.evaluate("a + b", None) {
66 Ok(result) => println!("Eval 'a + b' = {result}"),
67 Err(e) => println!("Eval failed: {e}"),
68 }
69 }
70 other => println!("Unexpected event: {other:?}"),
71 }
72
73 // Resume.
74 controller.continue_execution()?;
75
76 // Wait for completion.
77 let result = handle.join().unwrap()?;
78 println!("Lua returned: {result}");
79
80 Ok(())
81}Sourcepub fn detach(&self, lua: &Lua)
pub fn detach(&self, lua: &Lua)
Detach from the Lua instance and terminate the session.
If the VM is paused (blocked in the command loop), this sends
a disconnect command to unblock it. A DebugEvent::Terminated
event is emitted to notify the frontend.
After detach, this session instance should be dropped.
To debug again, create a new DebugSession.
Sourcepub fn register_source(
&self,
name: &str,
content: &str,
) -> Result<(), DebugError>
pub fn register_source( &self, name: &str, content: &str, ) -> Result<(), DebugError>
Register source code so the engine can validate breakpoints and display source context.
§Errors
Returns DebugError::Internal if the source lock is poisoned
(another thread panicked while holding it).
Sourcepub fn set_stop_on_entry(&self, stop: bool)
pub fn set_stop_on_entry(&self, stop: bool)
Set whether to pause on the first executable line.
Must be called before attach to guarantee
the setting takes effect before the first hook fires.
Sourcepub fn completion_notifier(&self) -> CompletionNotifier
pub fn completion_notifier(&self) -> CompletionNotifier
Create a CompletionNotifier for signaling execution completion.
Move the returned handle into the thread that runs Lua code.
Call CompletionNotifier::notify when execution finishes.
§Example
let notifier = session.completion_notifier();
std::thread::spawn(move || {
let result = lua.load("...").exec();
notifier.notify(result.err().map(|e| e.to_string()));
});Auto Trait Implementations§
impl Freeze for DebugSession
impl RefUnwindSafe for DebugSession
impl Send for DebugSession
impl Sync for DebugSession
impl Unpin for DebugSession
impl UnsafeUnpin for DebugSession
impl UnwindSafe for DebugSession
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more