firecracker-microvm/firecracker · error
Error getting initial gdb event
Error message
Error getting initial gdb event
What it means
Panic in `run_gdb_event_loop` (event_loop.rs:35): `target.gdb_event.recv().expect("Error getting initial gdb event")` fails because `recv()` returned Err, which on a crossbeam/std channel means every sender was dropped — the vcpu that should report hitting the entry-point hardware breakpoint exited (or panicked) before ever sending the initial debug event.
Source
Thrown at src/vmm/src/gdb/event_loop.rs:35
use crate::Vmm;
use crate::logger::{error, trace};
/// Starts the GDB event loop which acts as a proxy between the Vcpus and GDB
pub fn event_loop(
connection: UnixStream,
vmm: Arc<Mutex<Vmm>>,
gdb_event_receiver: Receiver<usize>,
entry_addr: GuestAddress,
) {
let target = FirecrackerTarget::new(vmm, gdb_event_receiver, entry_addr);
let connection: Box<dyn ConnectionExt<Error = std::io::Error>> = { Box::new(connection) };
let debugger = GdbStub::new(connection);
// We wait for the VM to reach the inital breakpoint we inserted before starting the event loop
target
.gdb_event
.recv()
.expect("Error getting initial gdb event");
gdb_event_loop_thread(debugger, target);
}
struct GdbBlockingEventLoop {}
impl run_blocking::BlockingEventLoop for GdbBlockingEventLoop {
type Target = FirecrackerTarget;
type Connection = Box<dyn ConnectionExt<Error = std::io::Error>>;
type StopReason = MultiThreadStopReason<u64>;
/// Poll for events from either Vcpu's or packets from the GDB connection
fn wait_for_stop_reason(
target: &mut FirecrackerTarget,
conn: &mut Self::Connection,
) -> Result<
run_blocking::Event<MultiThreadStopReason<u64>>,View on GitHub (pinned to 0a745def42)
Solutions
- Verify the entry-point address configured for GDB actually matches the guest kernel entry that vcpu 0 will reach
- Ensure the VM is started (vcpus running) after gdb_thread installs the entry breakpoint — do not stop the VM before the initial breakpoint is hit
- Replace the expect with graceful handling: on Err, log and bail out of the gdb loop instead of panicking
- Check vcpu thread logs for an earlier panic that dropped the sender
Example fix
// before
target
.gdb_event
.recv()
.expect("Error getting initial gdb event");
// after
if target.gdb_event.recv().is_err() {
warn!("gdb: vcpu sender dropped before the initial breakpoint event");
return;
} Defensive patterns
Strategy: validation
Validate before calling
// Before gdb_thread blocks on recv(): make sure vcpus are running and the entry bp is installed
{
let vmm = vmm.lock().unwrap();
assert!(!vmm.vm.as_kvm().unwrap().vcpus_handles().is_empty(),
"no running vcpus to hit the entry breakpoint");
}
// guest entry must be reachable: validate entry_addr against the kernel image/boot flow Prevention
- Set entry_addr from the same source the vcpu boot path uses (kernel entry point), never a hardcoded guess
- Do not stop the microvm between gdb socket setup and the first breakpoint hit
- Watch vcpu thread logs: a dropped sender usually means the vcpu panicked or exited first
When it happens
Trigger: GDB configured, `gdb_thread` sets a hw breakpoint at `entry_addr` and blocks on the channel; the vcpu sender is destroyed before sending — e.g. VM is stopped/killed first, the vcpu thread panics, or the guest never reaches entry_addr before the process tears down and the sender is dropped.
Common situations: Wrong `entry_addr` passed to the GDB config so the breakpoint is never hit while the sender lifetime ends at shutdown; microvm configured to pause/exit immediately; race between `StopMicrovm`/shutdown and the gdb handshake; vcpu thread crash before first debug exit.
Related errors
AI-assisted analysis of firecracker-microvm/firecracker@0a745def42 (2026-08-19).
Data as JSON: /api/errors/fd2a06bcf75364c0.
Report an issue: GitHub.