From 91873142165f44234cc6d20d0202408fb36bef51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 30 Oct 2017 18:43:04 +0800 Subject: [PATCH] monitor-manager-kms: Don't add outputs without modes There seems to be a kernel race when one disconnects an external monitor connected to a DisplayPort via a USB-C adapter. The race results in a connector being reported as connected, but without any modes supported. This had the side effect that we tried to set a preferred mode to the first listed mode, but as no modes were available, we instead tried to dereference the first element of a NULL array, causing a segmentation fault. Mitigate this by skipping adding output if no supported modes are advertised and the output doesn't support scaling, while moving the fallback path for calculating a preferred output mode to after possibly adding the common modes, to avoid the unvolentary NULL dereference. https://bugzilla.gnome.org/show_bug.cgi?id=789501 --- .../native/meta-monitor-manager-kms.c | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c index 23a79aedc..3b23625f2 100644 --- a/src/backends/native/meta-monitor-manager-kms.c +++ b/src/backends/native/meta-monitor-manager-kms.c @@ -692,7 +692,7 @@ init_crtc (MetaCrtc *crtc, crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify; } -static void +static gboolean init_output (MetaOutput *output, MetaMonitorManager *manager, drmModeConnector *connector, @@ -746,9 +746,6 @@ init_output (MetaOutput *output, output->preferred_mode = output->modes[i]; } - if (!output->preferred_mode) - output->preferred_mode = output->modes[0]; - output_kms->connector = connector; find_connector_properties (manager_kms, output_kms); @@ -759,6 +756,15 @@ init_output (MetaOutput *output, if (output_kms->has_scaling) add_common_modes (manager, output); + if (!output->modes) + { + meta_monitor_manager_clear_output (output); + return FALSE; + } + + if (!output->preferred_mode) + output->preferred_mode = output->modes[0]; + qsort (output->modes, output->n_modes, sizeof (MetaCrtcMode *), compare_modes); output_kms->n_encoders = connector->count_encoders; @@ -865,6 +871,8 @@ init_output (MetaOutput *output, output->backlight_min = 0; output->backlight_max = 0; output->backlight = -1; + + return TRUE; } static void @@ -1091,8 +1099,8 @@ init_outputs (MetaMonitorManager *manager, old_output = find_output_by_id (old_outputs, n_old_outputs, connector->connector_id); - init_output (output, manager, connector, old_output); - n_actual_outputs++; + if (init_output (output, manager, connector, old_output)) + n_actual_outputs++; } }