fbcond: retry handoff while display driver is not ready

The handoff is one-shot: inputd signals it the moment the real display
driver registers its path, but the driver's scheme may not serve the v2
open / capability query for a few more milliseconds. Without a retry, a
transient not-ready driver leaves the framebuffer permanently blank —
the login prompt is drawn to the framebuffer VT, so the console appears
dead even though boot continues on the serial mirror (observed as the
2026-07-20 '-vga std' boot freeze at 'Performing handoff').

Retry the reopen for up to 250 x 10ms; the driver becomes ready well
within this bound in practice. On success after retries, log the retry
count at info level. If the driver is still not ready after the bound,
emit a single explicit warning instead of per-attempt warn spam (the
per-attempt message in display.rs is demoted to debug). Serial mirror
remains unaffected in the failure case.
This commit is contained in:
Red Bear OS
2026-07-20 08:59:26 +09:00
parent e4d4dfffec
commit fb421083e0
2 changed files with 24 additions and 4 deletions
+3 -1
View File
@@ -45,7 +45,9 @@ impl Display {
let new_display_handle = match V2GraphicsHandle::from_file(display_file) {
Ok(handle) => handle,
Err(err) => {
log::warn!("fbcond: display not ready at handoff (from_file: {err}); will retry");
// Transient during the handoff race; handle_handoff retries and
// emits a single warning if it ultimately gives up.
log::debug!("fbcond: display not ready at handoff (from_file: {err}); will retry");
return;
}
};
+21 -3
View File
@@ -53,10 +53,28 @@ impl TextScreen {
pub fn handle_handoff(&mut self) {
log::info!("fbcond: Performing handoff");
self.display.reopen_for_handoff();
if self.display.map.is_some() {
self.flush_pending_writes();
// The handoff is one-shot: inputd signals it the moment the real display
// driver registers its path, but the driver's scheme may not serve the
// v2 open / capability query for a few more milliseconds. Without a
// retry, a transient not-ready driver leaves the framebuffer permanently
// blank (the login prompt is drawn to the framebuffer VT, so the console
// appears dead even though boot continues on the serial mirror). Retry
// briefly — the driver becomes ready well within this bound in practice.
for attempt in 0..250u32 {
self.display.reopen_for_handoff();
if self.display.map.is_some() {
if attempt > 0 {
log::info!("fbcond: handoff completed after {attempt} retries");
}
self.flush_pending_writes();
return;
}
std::thread::sleep(std::time::Duration::from_millis(10));
}
log::warn!(
"fbcond: display still not ready after handoff retries; \
framebuffer console will remain blank (serial mirror unaffected)"
);
}
pub fn input(&mut self, event: &Event) {