[mutter/gnome-3-26] monitor-manager-kms: Don't add outputs without modes



commit 91873142165f44234cc6d20d0202408fb36bef51
Author: Jonas Ådahl <jadahl gmail com>
Date:   Mon Oct 30 18:43:04 2017 +0800

    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

 src/backends/native/meta-monitor-manager-kms.c |   20 ++++++++++++++------
 1 files 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 23a79ae..3b23625 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++;
         }
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]