config: Make read_outputs failable
Previously we ignored when we had no output configuration **and** failed to apply the automatically created one. This leads to two problems: - If this happens on startup, we end up with no outputs being added to the shell and we quit. - If this happens later, we might end up in an inconsistent state, where the shell thinks we have an output, when it didn't light up for similar reasons. Thus `read_outputs` is failable and handling that very much depends on the where is was called from, because `read_outputs` doesn't know what configuration was active before. Thus make it failable and provide useful mitigations everywhere possible: - Try to enable just one output in case we fail on startup. - Don't enable any additional outputs, when we fail on hotplug. - Log the error like previously in any other case (and come up with more mitigations, once we understand these cases better).
This commit is contained in:
parent
cd1117080c
commit
b83e9f1d32
8 changed files with 232 additions and 91 deletions
56
src/state.rs
56
src/state.rs
|
|
@ -775,7 +775,7 @@ impl State {
|
|||
#[cfg(feature = "systemd")]
|
||||
{
|
||||
use smithay::backend::session::Session;
|
||||
use tracing::{debug, error};
|
||||
use tracing::{debug, error, warn};
|
||||
|
||||
let outputs = self.backend.lock().all_outputs();
|
||||
let is_active = match &self.backend {
|
||||
|
|
@ -793,17 +793,42 @@ impl State {
|
|||
debug!("Inhibiting lid switch");
|
||||
self.common.inhibit_lid_fd = Some(fd);
|
||||
|
||||
if crate::dbus::logind::lid_closed().unwrap_or(false) {
|
||||
self.backend.lock().disable_internal_output(
|
||||
let backend = self.backend.lock();
|
||||
let output = backend
|
||||
.all_outputs()
|
||||
.iter()
|
||||
.find(|o| o.is_internal())
|
||||
.cloned();
|
||||
let closed = crate::dbus::logind::lid_closed().unwrap_or(false);
|
||||
|
||||
if closed {
|
||||
backend.disable_internal_output(
|
||||
&mut self.common.output_configuration_state,
|
||||
);
|
||||
} else {
|
||||
self.backend.lock().enable_internal_output(
|
||||
backend.enable_internal_output(
|
||||
&mut self.common.output_configuration_state,
|
||||
);
|
||||
}
|
||||
std::mem::drop(backend);
|
||||
|
||||
self.refresh_output_config();
|
||||
if let Err(err) = self.refresh_output_config() {
|
||||
if !closed {
|
||||
warn!(?err, "Failed to re-enable internal connector");
|
||||
if let Some(output) = output {
|
||||
output.config_mut().enabled = OutputState::Disabled;
|
||||
if let Err(err) = self.refresh_output_config() {
|
||||
error!(
|
||||
"Unrecoverable output configuration error: {}",
|
||||
err
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Disabling an output should never fail.
|
||||
error!("Unrecoverable output configuration error: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
error!("Failed to inhibit lid switch: {}", err);
|
||||
|
|
@ -814,11 +839,24 @@ impl State {
|
|||
if let Some(_fd) = self.common.inhibit_lid_fd.take() {
|
||||
debug!("Removing inhibitor-lock on lid switch");
|
||||
|
||||
self.backend
|
||||
.lock()
|
||||
.enable_internal_output(&mut self.common.output_configuration_state);
|
||||
let backend = self.backend.lock();
|
||||
let output = backend
|
||||
.all_outputs()
|
||||
.iter()
|
||||
.find(|o| o.is_internal())
|
||||
.cloned();
|
||||
backend.enable_internal_output(&mut self.common.output_configuration_state);
|
||||
std::mem::drop(backend);
|
||||
|
||||
self.refresh_output_config();
|
||||
if let Err(err) = self.refresh_output_config() {
|
||||
warn!(?err, "Failed to re-enable internal connector");
|
||||
if let Some(output) = output {
|
||||
output.config_mut().enabled = OutputState::Disabled;
|
||||
if let Err(err) = self.refresh_output_config() {
|
||||
error!("Unrecoverable output configuration error: {}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
// drop _fd
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue