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
This commit is contained in:
parent
634f48a1cf
commit
9187314216
@ -692,7 +692,7 @@ init_crtc (MetaCrtc *crtc,
|
|||||||
crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
|
crtc->driver_notify = (GDestroyNotify) meta_crtc_destroy_notify;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
init_output (MetaOutput *output,
|
init_output (MetaOutput *output,
|
||||||
MetaMonitorManager *manager,
|
MetaMonitorManager *manager,
|
||||||
drmModeConnector *connector,
|
drmModeConnector *connector,
|
||||||
@ -746,9 +746,6 @@ init_output (MetaOutput *output,
|
|||||||
output->preferred_mode = output->modes[i];
|
output->preferred_mode = output->modes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!output->preferred_mode)
|
|
||||||
output->preferred_mode = output->modes[0];
|
|
||||||
|
|
||||||
output_kms->connector = connector;
|
output_kms->connector = connector;
|
||||||
find_connector_properties (manager_kms, output_kms);
|
find_connector_properties (manager_kms, output_kms);
|
||||||
|
|
||||||
@ -759,6 +756,15 @@ init_output (MetaOutput *output,
|
|||||||
if (output_kms->has_scaling)
|
if (output_kms->has_scaling)
|
||||||
add_common_modes (manager, output);
|
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);
|
qsort (output->modes, output->n_modes, sizeof (MetaCrtcMode *), compare_modes);
|
||||||
|
|
||||||
output_kms->n_encoders = connector->count_encoders;
|
output_kms->n_encoders = connector->count_encoders;
|
||||||
@ -865,6 +871,8 @@ init_output (MetaOutput *output,
|
|||||||
output->backlight_min = 0;
|
output->backlight_min = 0;
|
||||||
output->backlight_max = 0;
|
output->backlight_max = 0;
|
||||||
output->backlight = -1;
|
output->backlight = -1;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -1091,7 +1099,7 @@ init_outputs (MetaMonitorManager *manager,
|
|||||||
|
|
||||||
old_output = find_output_by_id (old_outputs, n_old_outputs,
|
old_output = find_output_by_id (old_outputs, n_old_outputs,
|
||||||
connector->connector_id);
|
connector->connector_id);
|
||||||
init_output (output, manager, connector, old_output);
|
if (init_output (output, manager, connector, old_output))
|
||||||
n_actual_outputs++;
|
n_actual_outputs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user